automation_object 0.0.4
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 +7 -0
- data/lib/automation_object/blue_print.rb +106 -0
- data/lib/automation_object/blue_print_validation/base_validation.rb +44 -0
- data/lib/automation_object/blue_print_validation/common_methods.rb +106 -0
- data/lib/automation_object/blue_print_validation/element_validation.rb +198 -0
- data/lib/automation_object/blue_print_validation/formatted_errors.rb +41 -0
- data/lib/automation_object/blue_print_validation/hook_validation.rb +393 -0
- data/lib/automation_object/blue_print_validation/key_value_constants.rb +75 -0
- data/lib/automation_object/blue_print_validation/modal_validation.rb +37 -0
- data/lib/automation_object/blue_print_validation/screen_modal_common_methods.rb +119 -0
- data/lib/automation_object/blue_print_validation/screen_validation.rb +21 -0
- data/lib/automation_object/blue_print_validation/validation_object.rb +32 -0
- data/lib/automation_object/driver/anonymous.rb +27 -0
- data/lib/automation_object/driver/driver.rb +281 -0
- data/lib/automation_object/driver/element.rb +243 -0
- data/lib/automation_object/element/element.rb +145 -0
- data/lib/automation_object/element/element_array.rb +12 -0
- data/lib/automation_object/element/element_cell.rb +126 -0
- data/lib/automation_object/element/element_group.rb +33 -0
- data/lib/automation_object/element/element_hash.rb +25 -0
- data/lib/automation_object/element/element_helpers.rb +29 -0
- data/lib/automation_object/element/element_methods.rb +134 -0
- data/lib/automation_object/element/elements_helpers.rb +204 -0
- data/lib/automation_object/framework/events.rb +8 -0
- data/lib/automation_object/framework/helpers.rb +101 -0
- data/lib/automation_object/framework/print_objects.rb +67 -0
- data/lib/automation_object/framework/screen_monitor.rb +55 -0
- data/lib/automation_object/framework/screen_routing.rb +310 -0
- data/lib/automation_object/framework/window_helpers.rb +181 -0
- data/lib/automation_object/framework.rb +408 -0
- data/lib/automation_object/hash.rb +6 -0
- data/lib/automation_object/hook_helpers.rb +27 -0
- data/lib/automation_object/logger.rb +179 -0
- data/lib/automation_object/object.rb +22 -0
- data/lib/automation_object/screen/modal.rb +8 -0
- data/lib/automation_object/screen/screen.rb +209 -0
- data/lib/automation_object/screen/screen_hook_helpers.rb +319 -0
- data/lib/automation_object/screen/screen_modal_helpers.rb +101 -0
- data/lib/automation_object/screen/screen_prompt_helpers.rb +21 -0
- data/lib/automation_object/screen/screen_window_helpers.rb +149 -0
- data/lib/automation_object/version.rb +3 -0
- data/lib/automation_object.rb +80 -0
- metadata +279 -0
@@ -0,0 +1,393 @@
|
|
1
|
+
module AutomationObject
|
2
|
+
module BluePrintValidation
|
3
|
+
module HookValidation
|
4
|
+
def validate_hooks
|
5
|
+
error_messages = Array.new
|
6
|
+
|
7
|
+
hooks = self.get_hooks
|
8
|
+
hooks.each { |hook|
|
9
|
+
#Set level string and get it out of the way
|
10
|
+
level_key_string = self.get_hook_level(hook)
|
11
|
+
|
12
|
+
#Skip checking if nil, being nice
|
13
|
+
next if hook[:configuration] == nil
|
14
|
+
|
15
|
+
unless hook[:configuration].is_a?(Hash)
|
16
|
+
error_message = "(#{level_key_string}) hook key (#{hook[:hook_name]}) is an invalid value type, expecting: ("
|
17
|
+
error_message << Hash.to_s
|
18
|
+
error_message << "), got: (#{hook[:configuration].class.to_s})"
|
19
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
20
|
+
|
21
|
+
next #Skip any additional validation on this
|
22
|
+
end
|
23
|
+
|
24
|
+
#before_load has no sub actions so go straight to validate_hook_action and skip this validation
|
25
|
+
if hook[:hook_name] == 'before_load'
|
26
|
+
error_messages += self.validate_hook_action(hook, hook[:hook_name], hook[:configuration])
|
27
|
+
next
|
28
|
+
end
|
29
|
+
|
30
|
+
hook[:configuration].each { |hook_action, hook_action_configuration|
|
31
|
+
#Check if valid element keys
|
32
|
+
hook_pair_types = KeyValueConstants::HOOK_PAIR_TYPES.clone
|
33
|
+
hook_pair_types.delete('elements') unless hook[:hook_name] == 'live?'
|
34
|
+
|
35
|
+
unless hook_pair_types.keys.include?(hook_action)
|
36
|
+
error_message = "(#{level_key_string}) level key (#{hook[:hook_name]}) sub key (#{hook_action}) "
|
37
|
+
error_message << 'is not a valid key, available hook sub level keys ('
|
38
|
+
error_message << hook_pair_types.keys.join(', ').to_s + ')'
|
39
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
40
|
+
|
41
|
+
next #skip if not a valid key since we are not going to check value
|
42
|
+
end
|
43
|
+
|
44
|
+
#Skip checking if nil, being nice
|
45
|
+
next if hook_action_configuration == nil
|
46
|
+
|
47
|
+
#Check sub element value
|
48
|
+
unless hook_action_configuration.is_a?(KeyValueConstants::HOOK_PAIR_TYPES[hook_action])
|
49
|
+
error_message = "(#{level_key_string}) level key (#{hook[:hook_name]}) sub key (#{hook_action}) "
|
50
|
+
error_message << 'has an invalid value type, expected: ('
|
51
|
+
error_message << KeyValueConstants::HOOK_PAIR_TYPES[hook_action].to_s
|
52
|
+
error_message << "), got: (#{hook_action_configuration.class.to_s})"
|
53
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
54
|
+
|
55
|
+
next #Skip any additional validation on this
|
56
|
+
end
|
57
|
+
|
58
|
+
error_messages += self.validate_hook_action(hook, hook_action, hook_action_configuration)
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
return error_messages
|
63
|
+
end
|
64
|
+
|
65
|
+
def validate_hook_action(hook, action, hook_action_configuration)
|
66
|
+
error_messages = Array.new
|
67
|
+
return error_messages if hook_action_configuration == nil #Being nice
|
68
|
+
|
69
|
+
level_key_string = self.get_hook_level(hook, action)
|
70
|
+
|
71
|
+
#Skip if elements action and use validate_elements_hook
|
72
|
+
if action == 'elements'
|
73
|
+
return self.validate_elements_hook(hook, action, hook_action_configuration)
|
74
|
+
end
|
75
|
+
|
76
|
+
unless hook_action_configuration.is_a?(Hash)
|
77
|
+
error_message = "(#{level_key_string}) hook action is an invalid value type, expecting: ("
|
78
|
+
error_message << Hash.to_s
|
79
|
+
error_message << "), got: (#{hook_action_configuration.class.to_s})"
|
80
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
81
|
+
|
82
|
+
return error_messages #Skip any additional validation on this
|
83
|
+
end
|
84
|
+
|
85
|
+
hook_action_configuration.each { |sub_action_key, sub_action_value|
|
86
|
+
#Check if valid sub hook action keys
|
87
|
+
unless KeyValueConstants::HOOK_ACTION_PAIR_TYPES.keys.include?(sub_action_key)
|
88
|
+
error_message = "(#{level_key_string}) level sub key (#{sub_action_key}) "
|
89
|
+
error_message << 'is not a valid key, available (hook action) sub level keys ('
|
90
|
+
error_message << KeyValueConstants::HOOK_ACTION_PAIR_TYPES.keys.join(', ').to_s + ')'
|
91
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
92
|
+
|
93
|
+
next #skip if not a valid key since we are not going to check value
|
94
|
+
end
|
95
|
+
|
96
|
+
#Skip checking if nil, being nice
|
97
|
+
next if sub_action_value == nil
|
98
|
+
|
99
|
+
#Check sub hook action value
|
100
|
+
unless sub_action_value.is_a?(KeyValueConstants::HOOK_ACTION_PAIR_TYPES[sub_action_key])
|
101
|
+
error_message = "(#{level_key_string}) level sub key (#{sub_action_key}) "
|
102
|
+
error_message << 'has an invalid value type, expected: ('
|
103
|
+
error_message << KeyValueConstants::HOOK_ACTION_PAIR_TYPES[sub_action_key].to_s
|
104
|
+
error_message << "), got: (#{sub_action_key.class.to_s})"
|
105
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
106
|
+
|
107
|
+
next #Skip any additional validation on this
|
108
|
+
end
|
109
|
+
|
110
|
+
#wait_for_elements test with validate_elements_hook, same set up as live?/elements
|
111
|
+
if sub_action_key == 'wait_for_elements'
|
112
|
+
error_messages += self.validate_elements_hook(hook, action, sub_action_key, sub_action_value)
|
113
|
+
next
|
114
|
+
end
|
115
|
+
|
116
|
+
case sub_action_key
|
117
|
+
when 'show_modal'
|
118
|
+
if hook[:view_name]
|
119
|
+
modal_exists = self.view_has_modal?(hook[:view_name], sub_action_value)
|
120
|
+
else
|
121
|
+
modal_exists = self.screen_has_modal?(hook[:screen_name], sub_action_value)
|
122
|
+
end
|
123
|
+
|
124
|
+
unless modal_exists
|
125
|
+
error_message = "(#{level_key_string}) level sub key (#{sub_action_key}) value (#{sub_action_value}) "
|
126
|
+
error_message << 'modal does not exist in '
|
127
|
+
|
128
|
+
if hook[:view_name]
|
129
|
+
error_message << "view (#{hook[:view_name]}), available modals ("
|
130
|
+
error_message << self.get_view_modals(hook[:view_name]).join(', ')
|
131
|
+
error_message << ')'
|
132
|
+
else
|
133
|
+
error_message << "screen (#{hook[:screen_name]}), available modals ("
|
134
|
+
error_message << self.get_screen_modals(hook[:screen_name]).join(', ')
|
135
|
+
error_message << ')'
|
136
|
+
end
|
137
|
+
|
138
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
139
|
+
end
|
140
|
+
when 'change_screen'
|
141
|
+
unless self.screen_exists?(sub_action_value)
|
142
|
+
error_message = "(#{level_key_string}/#{sub_action_key}) value (#{sub_action_value}) is not a defined screen. Available screens ("
|
143
|
+
error_message << self.get_screens.join(', ')
|
144
|
+
error_message << ')'
|
145
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
146
|
+
end
|
147
|
+
end
|
148
|
+
}
|
149
|
+
|
150
|
+
return error_messages
|
151
|
+
end
|
152
|
+
|
153
|
+
def validate_elements_hook(hook, action, sub_action_key = false, hook_action_configuration)
|
154
|
+
error_messages = Array.new
|
155
|
+
return error_messages if hook_action_configuration == nil
|
156
|
+
|
157
|
+
if action == 'before_load'
|
158
|
+
action = "#{sub_action_key}" if sub_action_key.is_a?(String)
|
159
|
+
else
|
160
|
+
action = action + "/#{sub_action_key}" if sub_action_key.is_a?(String)
|
161
|
+
end
|
162
|
+
|
163
|
+
level_key_string = self.get_hook_level(hook, action)
|
164
|
+
|
165
|
+
unless hook_action_configuration.is_a?(Array)
|
166
|
+
error_message = "(#{level_key_string}) level key is an invalid value type, expecting: ("
|
167
|
+
error_message << Array.to_s
|
168
|
+
error_message << "), got: (#{hook_action_configuration.class.to_s})"
|
169
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
170
|
+
|
171
|
+
return error_messages #Skip any further validation
|
172
|
+
end
|
173
|
+
|
174
|
+
hook_action_configuration.each_with_index { |element_hash, index|
|
175
|
+
unless element_hash.is_a?(Hash)
|
176
|
+
error_message = "(#{level_key_string}/#{index.to_s}) level key is an invalid value type, expecting: ("
|
177
|
+
error_message << Hash.to_s
|
178
|
+
error_message << "), got: (#{element_hash.class.to_s})"
|
179
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
180
|
+
|
181
|
+
next #Skip any additional validation on this
|
182
|
+
end
|
183
|
+
|
184
|
+
unless element_hash.has_key?('element_name')
|
185
|
+
error_message = "(#{level_key_string}/#{index.to_s}) level key Hash requires the element_name key"
|
186
|
+
error_message << Hash.to_s
|
187
|
+
error_message << "), got: (#{element_hash.class.to_s})"
|
188
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
189
|
+
end
|
190
|
+
|
191
|
+
acceptable_keys = KeyValueConstants::ELEMENT_KEYS + ['element_name']
|
192
|
+
acceptable_keys += self.get_element_custom_methods_via_hook(hook, element_hash['element_name'])
|
193
|
+
element_hash.each { |sub_element_key, sub_element_value|
|
194
|
+
unless acceptable_keys.include?(sub_element_key)
|
195
|
+
error_message = "(#{level_key_string}/#{index.to_s}) level sub key (#{sub_element_key}) "
|
196
|
+
error_message << 'is not a valid key, available sub level keys ('
|
197
|
+
error_message << acceptable_keys.join(', ').to_s + ')'
|
198
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
199
|
+
|
200
|
+
next #skip if not a valid key since we are not going to check value
|
201
|
+
end
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
return error_messages
|
206
|
+
end
|
207
|
+
|
208
|
+
def get_element_custom_methods_via_hook(hook, element_name)
|
209
|
+
custom_methods = Array.new
|
210
|
+
|
211
|
+
if hook[:screen_name]
|
212
|
+
return custom_methods unless self.has_key?('screens')
|
213
|
+
return custom_methods unless self['screens'].class == Hash
|
214
|
+
return custom_methods unless self['screens'].has_key?(hook[:screen_name])
|
215
|
+
|
216
|
+
configuration = self['screens'][hook[:screen_name]]
|
217
|
+
else
|
218
|
+
return custom_methods unless self.has_key?('views')
|
219
|
+
return custom_methods unless self['views'].class == Hash
|
220
|
+
return custom_methods unless self['views'].has_key?(hook[:view_name])
|
221
|
+
|
222
|
+
configuration = self['views'][hook[:view_name]]
|
223
|
+
end
|
224
|
+
|
225
|
+
if hook[:modals]
|
226
|
+
return custom_methods unless configuration.has_key?('modals')
|
227
|
+
return custom_methods unless configuration['modals'].class == Hash
|
228
|
+
return custom_methods unless configuration['modals'].has_key?(hook[:modal_name])
|
229
|
+
|
230
|
+
configuration = configuration['modals'][hook[:modal_name]]
|
231
|
+
end
|
232
|
+
|
233
|
+
return custom_methods unless configuration.class == Hash
|
234
|
+
return custom_methods unless configuration.has_key?('elements')
|
235
|
+
return custom_methods unless configuration['elements'].class == Hash
|
236
|
+
return custom_methods unless configuration['elements'].has_key?(element_name)
|
237
|
+
|
238
|
+
element_configuration = configuration['elements'][element_name]
|
239
|
+
|
240
|
+
return custom_methods unless element_configuration.class == Hash
|
241
|
+
return custom_methods unless element_configuration.has_key?('custom_methods')
|
242
|
+
return custom_methods unless element_configuration['custom_methods'].class == Hash
|
243
|
+
|
244
|
+
return element_configuration['custom_methods'].keys
|
245
|
+
end
|
246
|
+
|
247
|
+
def get_hook_level(hook, hook_action = false)
|
248
|
+
level_key_string = ''
|
249
|
+
if hook[:view_name]
|
250
|
+
level_key_string << "views/#{hook[:view_name]}"
|
251
|
+
else
|
252
|
+
level_key_string << "screens/#{hook[:screen_name]}"
|
253
|
+
end
|
254
|
+
|
255
|
+
level_key_string << "/modals/#{hook[:modal_name]}" if hook[:modal_name]
|
256
|
+
level_key_string << "/elements/#{hook[:element_name]}" if hook[:element_name]
|
257
|
+
|
258
|
+
level_key_string << "/#{hook[:hook_name]}" if hook[:hook_name]
|
259
|
+
level_key_string << "/#{hook_action}" if hook_action and hook_action != 'before_load'
|
260
|
+
|
261
|
+
return level_key_string
|
262
|
+
end
|
263
|
+
|
264
|
+
def get_hooks
|
265
|
+
hooks = Array.new
|
266
|
+
|
267
|
+
if self.has_key?('views') and self['views'].class == Hash
|
268
|
+
self['views'].each { |view_name, view_configuration|
|
269
|
+
next unless view_configuration.class == Hash
|
270
|
+
|
271
|
+
view_configuration.each { |sub_view_key, sub_view_configuration|
|
272
|
+
next unless KeyValueConstants::HOOK_KEYS.include?(sub_view_key)
|
273
|
+
|
274
|
+
hook = {:view_name => view_name, :hook_name => sub_view_key, :configuration => sub_view_configuration}
|
275
|
+
hooks.push(hook)
|
276
|
+
}
|
277
|
+
|
278
|
+
#Check for Modals
|
279
|
+
if view_configuration.has_key?('modals') and view_configuration['modals'].class == Hash
|
280
|
+
view_configuration['modals'].each { |modal_name, modal_configuration|
|
281
|
+
next unless modal_configuration.class == Hash
|
282
|
+
|
283
|
+
modal_configuration.each { |sub_modal_key, sub_modal_configuration|
|
284
|
+
next unless KeyValueConstants::HOOK_KEYS.include?(sub_modal_key)
|
285
|
+
|
286
|
+
hook = {:view_name => view_name, :modal_name => modal_name,
|
287
|
+
:hook_name => sub_modal_key, :configuration => sub_modal_configuration}
|
288
|
+
hooks.push(hook)
|
289
|
+
}
|
290
|
+
|
291
|
+
next unless modal_configuration.has_key?('elements')
|
292
|
+
next unless modal_configuration['elements'].class == Hash
|
293
|
+
|
294
|
+
modal_configuration['elements'].each { |modal_element_name, modal_element_configuration|
|
295
|
+
next unless modal_element_configuration.class == Hash
|
296
|
+
|
297
|
+
modal_element_configuration.each { |sub_modal_element_key, sub_modal_element_configuration|
|
298
|
+
next unless KeyValueConstants::ELEMENT_KEYS.include?(sub_modal_element_key)
|
299
|
+
|
300
|
+
hook = {:view_name => view_name, :modal_name => modal_name,
|
301
|
+
:element_name => modal_element_name, :hook_name => sub_modal_element_key,
|
302
|
+
:configuration => sub_modal_element_configuration}
|
303
|
+
hooks.push(hook)
|
304
|
+
}
|
305
|
+
}
|
306
|
+
}
|
307
|
+
end
|
308
|
+
|
309
|
+
#Check for element hooks
|
310
|
+
next unless view_configuration.has_key?('elements')
|
311
|
+
next unless view_configuration['elements'].class == Hash
|
312
|
+
|
313
|
+
view_configuration['elements'].each { |element_name, element_configuration|
|
314
|
+
next unless element_configuration.class == Hash
|
315
|
+
|
316
|
+
element_configuration.each { |sub_element_key, sub_element_configuration|
|
317
|
+
next unless KeyValueConstants::ELEMENT_KEYS.include?(sub_element_key)
|
318
|
+
|
319
|
+
hook = {:view_name => view_name, :element_name => element_name,
|
320
|
+
:hook_name => sub_element_key, :configuration => sub_element_configuration}
|
321
|
+
hooks.push(hook)
|
322
|
+
}
|
323
|
+
}
|
324
|
+
}
|
325
|
+
end
|
326
|
+
|
327
|
+
return hooks unless self.has_key?('screens')
|
328
|
+
return hooks unless self['screens'].class == Hash
|
329
|
+
|
330
|
+
self['screens'].each { |screen_name, screen_configuration|
|
331
|
+
next unless screen_configuration.class == Hash
|
332
|
+
|
333
|
+
screen_configuration.each { |sub_screen_key, sub_screen_configuration|
|
334
|
+
next unless KeyValueConstants::HOOK_KEYS.include?(sub_screen_key)
|
335
|
+
|
336
|
+
hook = {:screen_name => screen_name, :hook_name => sub_screen_key,
|
337
|
+
:configuration => sub_screen_configuration}
|
338
|
+
hooks.push(hook)
|
339
|
+
}
|
340
|
+
|
341
|
+
#Check for Modals
|
342
|
+
if screen_configuration.has_key?('modals') and screen_configuration['modals'].class == Hash
|
343
|
+
screen_configuration['modals'].each { |modal_name, modal_configuration|
|
344
|
+
next unless modal_configuration.class == Hash
|
345
|
+
|
346
|
+
modal_configuration.each { |sub_modal_key, sub_modal_configuration|
|
347
|
+
next unless KeyValueConstants::HOOK_KEYS.include?(sub_modal_key)
|
348
|
+
|
349
|
+
hook = {:screen_name => screen_name, :modal_name => modal_name,
|
350
|
+
:hook_name => sub_modal_key, :configuration => sub_modal_configuration}
|
351
|
+
hooks.push(hook)
|
352
|
+
}
|
353
|
+
|
354
|
+
next unless modal_configuration.has_key?('elements')
|
355
|
+
next unless modal_configuration['elements'].class == Hash
|
356
|
+
|
357
|
+
modal_configuration['elements'].each { |modal_element_name, modal_element_configuration|
|
358
|
+
next unless modal_element_configuration.class == Hash
|
359
|
+
|
360
|
+
modal_element_configuration.each { |sub_modal_element_key, sub_modal_element_configuration|
|
361
|
+
next unless KeyValueConstants::ELEMENT_KEYS.include?(sub_modal_element_key)
|
362
|
+
|
363
|
+
hook = {:screen_name => screen_name, :modal_name => modal_name,
|
364
|
+
:element_name => modal_element_name, :hook_name => sub_modal_element_key,
|
365
|
+
:configuration => sub_modal_element_configuration}
|
366
|
+
hooks.push(hook)
|
367
|
+
}
|
368
|
+
}
|
369
|
+
}
|
370
|
+
end
|
371
|
+
|
372
|
+
#Check for element hooks
|
373
|
+
next unless screen_configuration.has_key?('elements')
|
374
|
+
next unless screen_configuration['elements'].class == Hash
|
375
|
+
|
376
|
+
screen_configuration['elements'].each { |element_name, element_configuration|
|
377
|
+
next unless element_configuration.class == Hash
|
378
|
+
|
379
|
+
element_configuration.each { |sub_element_key, sub_element_configuration|
|
380
|
+
next unless KeyValueConstants::ELEMENT_KEYS.include?(sub_element_key)
|
381
|
+
|
382
|
+
hook = {:screen_name => screen_name, :element_name => element_name,
|
383
|
+
:hook_name => sub_element_key, :configuration => sub_element_configuration}
|
384
|
+
hooks.push(hook)
|
385
|
+
}
|
386
|
+
}
|
387
|
+
}
|
388
|
+
|
389
|
+
return hooks
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module AutomationObject
|
2
|
+
module BluePrintValidation
|
3
|
+
module KeyValueConstants
|
4
|
+
ELEMENT_KEYS = ['length', 'exists?', 'click', 'visible?', 'invisible?',
|
5
|
+
'id', 'href', 'scroll_to_view', 'x', 'y', 'width', 'height', 'drag_to_element',
|
6
|
+
'get_element_center', 'name', 'value', 'type', 'clear', 'tag_name', 'text',
|
7
|
+
'size', 'location', 'rel_location', 'send_keys', 'set_value', 'displayed?', 'selected?',
|
8
|
+
'attribute', 'clear', 'attribute', 'click', 'css_value', 'displayed?', 'enabled?',
|
9
|
+
'location', 'location_once_scrolled_into_view', 'ref', 'selected?', 'send_keys',
|
10
|
+
'size', 'submit', 'tag_name', 'text', 'content']
|
11
|
+
|
12
|
+
HOOK_KEYS = ['live?', 'before_load', 'accept', 'dismiss', 'scroll_up', 'scroll_down', 'scroll_right', 'scroll_left']
|
13
|
+
|
14
|
+
BASE_PAIR_TYPES = {
|
15
|
+
'base_url' => String,
|
16
|
+
'default_screen' => String,
|
17
|
+
'throttle_element_interactions' => Hash,
|
18
|
+
'throttle_element_methods' => Hash,
|
19
|
+
'throttle_driver_methods' => Hash,
|
20
|
+
'screen_transition_sleep' => Numeric,
|
21
|
+
'views' => Hash,
|
22
|
+
'screens' => Hash
|
23
|
+
}
|
24
|
+
|
25
|
+
THROTTLE_ELEMENT_PAIR_TYPES = Hash[*ELEMENT_KEYS.collect { |v| [v, Numeric] }.flatten]
|
26
|
+
|
27
|
+
SCREEN_PAIR_TYPES = {
|
28
|
+
'modals' => Hash,
|
29
|
+
'included_views' => Array,
|
30
|
+
'automatic_screen_changes' => Array,
|
31
|
+
'elements' => Hash,
|
32
|
+
'element_groups' => Hash
|
33
|
+
}.merge(Hash[*HOOK_KEYS.collect { |v| [v, Hash] }.flatten])
|
34
|
+
|
35
|
+
MODAL_PAIR_TYPES = SCREEN_PAIR_TYPES
|
36
|
+
|
37
|
+
ELEMENT_PAIR_TYPES = {
|
38
|
+
'in_iframe' => String,
|
39
|
+
'css' => String,
|
40
|
+
'xpath' => String,
|
41
|
+
'multiple' => TrueClass,
|
42
|
+
'multiple_ios_fix' => TrueClass,
|
43
|
+
'define_elements_by' => String,
|
44
|
+
'custom_methods' => Hash,
|
45
|
+
'custom_range' => Hash,
|
46
|
+
'remove_duplicates' => String
|
47
|
+
}.merge(Hash[*ELEMENT_KEYS.collect { |v| [v, Hash] }.flatten])
|
48
|
+
|
49
|
+
ELEMENT_CUSTOM_METHOD_PAIR_TYPES = {
|
50
|
+
'element_method' => String,
|
51
|
+
'evaluate' => String
|
52
|
+
}
|
53
|
+
|
54
|
+
HOOK_PAIR_TYPES = {
|
55
|
+
'before' => Hash,
|
56
|
+
'after' => Hash,
|
57
|
+
'elements' => Array
|
58
|
+
}
|
59
|
+
|
60
|
+
HOOK_ACTION_PAIR_TYPES = {
|
61
|
+
'wait_for_new_window' => TrueClass,
|
62
|
+
'show_modal' => String,
|
63
|
+
'close_window' => TrueClass,
|
64
|
+
'change_screen' => String,
|
65
|
+
'sleep' => Numeric,
|
66
|
+
'wait_for_elements' => Array,
|
67
|
+
'change_to_previous_screen' => TrueClass,
|
68
|
+
'close_modal' => TrueClass,
|
69
|
+
'automatic_onload_modals' => Array,
|
70
|
+
'reset_screen' => TrueClass,
|
71
|
+
'possible_screen_changes' => Array
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module AutomationObject
|
2
|
+
module BluePrintValidation
|
3
|
+
module ModalValidation
|
4
|
+
include ScreenModalCommonMethods
|
5
|
+
|
6
|
+
def validate_modals
|
7
|
+
error_messages = Array.new
|
8
|
+
|
9
|
+
self.get_all_modals.each { |modal|
|
10
|
+
error_messages += self.validate_screen_modal(modal[:screen_name], modal[:modal_name], modal[:configuration])
|
11
|
+
}
|
12
|
+
|
13
|
+
return error_messages
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_all_modals
|
17
|
+
modals = Array.new
|
18
|
+
return modals unless self.has_key?('screens')
|
19
|
+
return modals unless self['screens'].class == Hash
|
20
|
+
|
21
|
+
self['screens'].each { |screen_name, screen_configuration|
|
22
|
+
next unless screen_configuration.class == Hash
|
23
|
+
next unless screen_configuration.has_key?('modals')
|
24
|
+
next unless screen_configuration['modals'].class == Hash
|
25
|
+
|
26
|
+
screen_configuration['modals'].each { |modal_name, modal_configuration|
|
27
|
+
next if modal_configuration == nil
|
28
|
+
modal = {:screen_name => screen_name, :modal_name => modal_name, :configuration => modal_configuration}
|
29
|
+
modals.push(modal)
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
return modals
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module AutomationObject
|
2
|
+
module BluePrintValidation
|
3
|
+
module ScreenModalCommonMethods
|
4
|
+
def validate_screen_modal(screen_name, modal_name = false, configuration)
|
5
|
+
error_messages = Array.new
|
6
|
+
|
7
|
+
if modal_name == false #Skip multiple errors
|
8
|
+
unless screen_name.is_a?(String)
|
9
|
+
error_message = "(screens) level key (#{screen_name}) is an invalid key type, expecting: ("
|
10
|
+
error_message << String.to_s
|
11
|
+
error_message << "), got: (#{screen_name.class.to_s})"
|
12
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
13
|
+
end
|
14
|
+
else
|
15
|
+
unless modal_name.is_a?(String)
|
16
|
+
error_message = "(screens/#{screen_name}/modals) level key (#{modal_name}) is an invalid key type, expecting: ("
|
17
|
+
error_message << String.to_s
|
18
|
+
error_message << "), got: (#{modal_name.class.to_s})"
|
19
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
return error_messages if configuration == nil
|
24
|
+
|
25
|
+
unless configuration.is_a?(Hash)
|
26
|
+
if modal_name == false
|
27
|
+
error_message = "(screens) level key (#{screen_name}) has an invalid value type, expecting: ("
|
28
|
+
else
|
29
|
+
error_message = "(screens/#{screen_name}/modals) level key (#{modal_name}) has an invalid value type, expecting: ("
|
30
|
+
end
|
31
|
+
|
32
|
+
error_message << Hash.to_s
|
33
|
+
error_message << "), got: (#{configuration.class.to_s})"
|
34
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
35
|
+
|
36
|
+
return error_messages
|
37
|
+
end
|
38
|
+
|
39
|
+
configuration.each { |sub_screen_key, sub_screen_value|
|
40
|
+
#Check if valid screen keys
|
41
|
+
unless KeyValueConstants::SCREEN_PAIR_TYPES.keys.include?(sub_screen_key)
|
42
|
+
if modal_name == false
|
43
|
+
error_message = "(screens) level key (#{screen_name}) sub key (#{sub_screen_key}) "
|
44
|
+
else
|
45
|
+
error_message = "(screens/#{screen_name}/modals) level key (#{modal_name}) sub key (#{sub_screen_key}) "
|
46
|
+
end
|
47
|
+
|
48
|
+
error_message << 'is not a valid key, available (screens) sub level keys ('
|
49
|
+
error_message << KeyValueConstants::SCREEN_PAIR_TYPES.keys.join(', ').to_s + ')'
|
50
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
51
|
+
|
52
|
+
next #skip if not a valid key since we are not going to check value
|
53
|
+
end
|
54
|
+
|
55
|
+
#Skip checking if nil, being nice
|
56
|
+
next if sub_screen_value == nil
|
57
|
+
|
58
|
+
#Check sub screen value
|
59
|
+
unless sub_screen_value.is_a?(KeyValueConstants::SCREEN_PAIR_TYPES[sub_screen_key])
|
60
|
+
if modal_name == false
|
61
|
+
error_message = "(screens) level key (#{screen_name}) sub key (#{sub_screen_key}) "
|
62
|
+
else
|
63
|
+
error_message = "(screens/#{screen_name}/modals) level key (#{screen_name}) sub key (#{sub_screen_key}) "
|
64
|
+
end
|
65
|
+
|
66
|
+
error_message << 'has an invalid value type, expected: ('
|
67
|
+
error_message << KeyValueConstants::SCREEN_PAIR_TYPES[sub_screen_key].to_s
|
68
|
+
error_message << "), got: (#{sub_screen_value.class.to_s})"
|
69
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
70
|
+
|
71
|
+
next #Skip any additional validation on this
|
72
|
+
end
|
73
|
+
|
74
|
+
#More complex validation
|
75
|
+
case sub_screen_key
|
76
|
+
when 'included_views'
|
77
|
+
sub_screen_value.each { |included_view|
|
78
|
+
unless self.view_exists?(included_view)
|
79
|
+
if modal_name == false
|
80
|
+
error_message = "(screens) level key (#{screen_name}) sub key (#{sub_screen_key}) "
|
81
|
+
else
|
82
|
+
error_message = "(screens/#{screen_name}/modals) level key (#{screen_name}) sub key (#{sub_screen_key}) "
|
83
|
+
end
|
84
|
+
|
85
|
+
error_message << "included_view (#{included_view}) does not exist. Available views ("
|
86
|
+
error_message << self.get_views.join(', ')
|
87
|
+
error_message << ')'
|
88
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
89
|
+
end
|
90
|
+
}
|
91
|
+
when 'automatic_screen_changes'
|
92
|
+
sub_screen_value.each { |automatic_screen_change|
|
93
|
+
unless self.screen_exists?(automatic_screen_change)
|
94
|
+
error_message = "(screens) level key (#{screen_name}) sub key (#{sub_screen_key}) "
|
95
|
+
error_message << "screen (#{automatic_screen_change}) does not exist. Available screens ("
|
96
|
+
error_message << self.get_screens.join(', ')
|
97
|
+
error_message << ')'
|
98
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
99
|
+
|
100
|
+
next
|
101
|
+
end
|
102
|
+
|
103
|
+
unless self.screen_has_live?(automatic_screen_change)
|
104
|
+
error_message = "(screens) level key (#{screen_name}) sub key (#{sub_screen_key}) "
|
105
|
+
error_message << "screen (#{automatic_screen_change}) does not have live? configuration. "
|
106
|
+
error_message << 'Automatic screen changes need to have associated live? configurations.'
|
107
|
+
error_messages.push(FormattedErrors::format_message(error_message))
|
108
|
+
|
109
|
+
next
|
110
|
+
end
|
111
|
+
}
|
112
|
+
end
|
113
|
+
}
|
114
|
+
|
115
|
+
return error_messages
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module AutomationObject
|
2
|
+
module BluePrintValidation
|
3
|
+
module ScreenValidation
|
4
|
+
include ScreenModalCommonMethods
|
5
|
+
|
6
|
+
def validate_screens
|
7
|
+
error_messages = Array.new
|
8
|
+
return error_messages unless self.has_key?('screens')
|
9
|
+
return error_messages unless self['screens'].class == Hash
|
10
|
+
|
11
|
+
error_messages = Array.new
|
12
|
+
|
13
|
+
self['screens'].each { |screen_name, screen_configuration|
|
14
|
+
error_messages += self.validate_screen_modal(screen_name, screen_configuration)
|
15
|
+
}
|
16
|
+
|
17
|
+
return error_messages
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module AutomationObject
|
2
|
+
module BluePrintValidation
|
3
|
+
class ValidationObject < Hash
|
4
|
+
include CommonMethods
|
5
|
+
include BaseValidation
|
6
|
+
include ScreenValidation
|
7
|
+
include ModalValidation
|
8
|
+
include ElementValidation
|
9
|
+
include HookValidation
|
10
|
+
|
11
|
+
def initialize(blue_print_object)
|
12
|
+
#Figured on cloning the Hash Object, probably not needed
|
13
|
+
blue_print_object_cloned = blue_print_object.clone
|
14
|
+
|
15
|
+
blue_print_object_cloned.each { |key, value|
|
16
|
+
self[key] = value
|
17
|
+
}
|
18
|
+
|
19
|
+
error_messages = Array.new
|
20
|
+
error_messages += self.validate_base #BaseValidation Module
|
21
|
+
error_messages += self.validate_screens #ScreenValidation Module
|
22
|
+
error_messages += self.validate_modals
|
23
|
+
error_messages += self.validate_elements
|
24
|
+
error_messages += self.validate_hooks
|
25
|
+
|
26
|
+
if error_messages.length > 0
|
27
|
+
raise FormattedErrors::array_to_message(error_messages)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|