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.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/lib/automation_object/blue_print.rb +106 -0
  3. data/lib/automation_object/blue_print_validation/base_validation.rb +44 -0
  4. data/lib/automation_object/blue_print_validation/common_methods.rb +106 -0
  5. data/lib/automation_object/blue_print_validation/element_validation.rb +198 -0
  6. data/lib/automation_object/blue_print_validation/formatted_errors.rb +41 -0
  7. data/lib/automation_object/blue_print_validation/hook_validation.rb +393 -0
  8. data/lib/automation_object/blue_print_validation/key_value_constants.rb +75 -0
  9. data/lib/automation_object/blue_print_validation/modal_validation.rb +37 -0
  10. data/lib/automation_object/blue_print_validation/screen_modal_common_methods.rb +119 -0
  11. data/lib/automation_object/blue_print_validation/screen_validation.rb +21 -0
  12. data/lib/automation_object/blue_print_validation/validation_object.rb +32 -0
  13. data/lib/automation_object/driver/anonymous.rb +27 -0
  14. data/lib/automation_object/driver/driver.rb +281 -0
  15. data/lib/automation_object/driver/element.rb +243 -0
  16. data/lib/automation_object/element/element.rb +145 -0
  17. data/lib/automation_object/element/element_array.rb +12 -0
  18. data/lib/automation_object/element/element_cell.rb +126 -0
  19. data/lib/automation_object/element/element_group.rb +33 -0
  20. data/lib/automation_object/element/element_hash.rb +25 -0
  21. data/lib/automation_object/element/element_helpers.rb +29 -0
  22. data/lib/automation_object/element/element_methods.rb +134 -0
  23. data/lib/automation_object/element/elements_helpers.rb +204 -0
  24. data/lib/automation_object/framework/events.rb +8 -0
  25. data/lib/automation_object/framework/helpers.rb +101 -0
  26. data/lib/automation_object/framework/print_objects.rb +67 -0
  27. data/lib/automation_object/framework/screen_monitor.rb +55 -0
  28. data/lib/automation_object/framework/screen_routing.rb +310 -0
  29. data/lib/automation_object/framework/window_helpers.rb +181 -0
  30. data/lib/automation_object/framework.rb +408 -0
  31. data/lib/automation_object/hash.rb +6 -0
  32. data/lib/automation_object/hook_helpers.rb +27 -0
  33. data/lib/automation_object/logger.rb +179 -0
  34. data/lib/automation_object/object.rb +22 -0
  35. data/lib/automation_object/screen/modal.rb +8 -0
  36. data/lib/automation_object/screen/screen.rb +209 -0
  37. data/lib/automation_object/screen/screen_hook_helpers.rb +319 -0
  38. data/lib/automation_object/screen/screen_modal_helpers.rb +101 -0
  39. data/lib/automation_object/screen/screen_prompt_helpers.rb +21 -0
  40. data/lib/automation_object/screen/screen_window_helpers.rb +149 -0
  41. data/lib/automation_object/version.rb +3 -0
  42. data/lib/automation_object.rb +80 -0
  43. metadata +279 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c36cc7abfa4e9979ce44a0944d93226186e95322
4
+ data.tar.gz: 3c7a3f82d088f77f7fc8decb354eeafa5694632d
5
+ SHA512:
6
+ metadata.gz: c2ece489fe81158e7aa27736e461042c8577180215b24cc0f01d0820e46e163b74b3a594dfb8b886fcdcede3426d84ea15ea7660826934d09311b33f7ae8bc68
7
+ data.tar.gz: 3fbbfa38f5f69f88e21eac36987a9b83f030f769bf211412d97dad5501a3ce6e4e1d65f661fdf731c0242579736134c510fe22565df2830eb19bd7f6ebc5bfb3
@@ -0,0 +1,106 @@
1
+ module AutomationObject
2
+ class BluePrint < Hash
3
+ #Static
4
+ @@max_folder_depth = 10
5
+ @@base_directory = nil
6
+ @@validate_blueprint = false
7
+
8
+ def self.max_folder_depth
9
+ @@max_folder_depth
10
+ end
11
+
12
+ def self.max_folder_depth=(value)
13
+ @@max_folder_depth = value
14
+ end
15
+
16
+ def self.base_directory
17
+ @@base_directory
18
+ end
19
+
20
+ def self.base_directory=(value)
21
+ @@base_directory = value
22
+ end
23
+
24
+ def self.validate_blueprint
25
+ @@validate_blueprint
26
+ end
27
+
28
+ def self.validate_blueprint=(value)
29
+ @@validate_blueprint = value
30
+ end
31
+
32
+ #Instance
33
+ def initialize(path)
34
+ full_path = path
35
+ full_path = File.join(@@base_directory, path) if @@base_directory
36
+
37
+ unless File.directory?(full_path)
38
+ raise ArgumentError, "Blue prints directory doesn't exist: #{full_path}"
39
+ end
40
+
41
+ @configuration = Hash.new
42
+ self.merge_directory(full_path)
43
+
44
+ if @@validate_blueprint
45
+ BluePrintValidation::ValidationObject.new(self)
46
+ end
47
+
48
+ self.merge_views
49
+ end
50
+
51
+ def merge_directory(path, depth = 0)
52
+ raise ArgumentError, "Folder depth breached max depth of #{@@max_folder_depth}" if depth > @@max_folder_depth
53
+
54
+ unless File.directory?(path)
55
+ raise ArgumentError, "Blue print path doesn't exist: #{path}"
56
+ end
57
+
58
+ Dir.foreach(path) do |item|
59
+ next if item == '.' or item == '..'
60
+ next if item[0] == '.'
61
+
62
+ file_path = File.join(path, "#{item}")
63
+ if File.directory?(file_path)
64
+ depth = depth + 1
65
+ self.merge_directory("#{path}/#{item}", depth) #call this method again for the subdirectory
66
+ next
67
+ end
68
+
69
+ next unless self.is_yaml_file?(file_path)
70
+
71
+ file_configuration = YAML.load_file(file_path)
72
+ @configuration = @configuration.deep_merge(file_configuration) if file_configuration.class == Hash
73
+ end
74
+
75
+ @configuration.each { |key, value|
76
+ self[key] = value
77
+ }
78
+ end
79
+
80
+ def is_yaml_file?(file_path)
81
+ return (file_path.match(/\.ya?ml$/)) ? true : false
82
+ end
83
+
84
+ def merge_views
85
+ return unless self['screens'].is_a?(Hash)
86
+ return unless self['views'].is_a?(Hash)
87
+
88
+ self['screens'].each { |screen_name, screen_configuration|
89
+ next unless screen_configuration.is_a?(Hash)
90
+ next unless screen_configuration['included_views'].is_a?(Array)
91
+
92
+ screen_configuration['elements'] = Hash.new unless screen_configuration['elements'].class == Hash
93
+
94
+ screen_configuration['included_views'].each { |view|
95
+ next unless self['views'][view].is_a?(Hash)
96
+ self['views'][view]['elements'] = Hash.new unless self['views'][view]['elements'].is_a?(Hash)
97
+ screen_configuration = screen_configuration.deep_merge(self['views'][view])
98
+ }
99
+
100
+ self['screens'][screen_name] = screen_configuration
101
+ }
102
+
103
+ self.delete('views')
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,44 @@
1
+ module AutomationObject
2
+ module BluePrintValidation
3
+ module BaseValidation
4
+ def validate_base
5
+ error_messages = Array.new
6
+
7
+ self.each { |base_key, base_value|
8
+ #Check if valid base keys
9
+ unless KeyValueConstants::BASE_PAIR_TYPES.keys.include?(base_key)
10
+ error_message = "Base level key (#{base_key}) is not a valid key, available base level keys ("
11
+ error_message << KeyValueConstants::BASE_PAIR_TYPES.keys.join(', ').to_s + ')'
12
+ error_messages.push(FormattedErrors::format_message(error_message))
13
+
14
+ next #skip if not a valid key since we are not going to check value
15
+ end
16
+
17
+ #Skip checking if nil, being nice
18
+ next if base_value == nil
19
+
20
+ unless base_value.is_a?(KeyValueConstants::BASE_PAIR_TYPES[base_key])
21
+ error_message = "Base level key (#{base_key}) has an invalid value type, expecting: ("
22
+ error_message << KeyValueConstants::BASE_PAIR_TYPES[base_key].to_s
23
+ error_message << "), got: (#{base_value.class.to_s})"
24
+ error_messages.push(FormattedErrors::format_message(error_message))
25
+
26
+ next #Skip any additional validation on this
27
+ end
28
+
29
+ case base_key
30
+ when 'default_screen'
31
+ unless self.screen_exists?(self[base_key])
32
+ error_message = "(#{base_key}) value has screen that does not exist (#{self[base_key]}), available screens ("
33
+ error_message << self.get_screens.join(', ').to_s
34
+ error_message << ')'
35
+ error_messages.push(FormattedErrors::format_message(error_message))
36
+ end
37
+ end
38
+ }
39
+
40
+ return error_messages
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,106 @@
1
+ module AutomationObject
2
+ module BluePrintValidation
3
+ module CommonMethods
4
+ def get_screens
5
+ screens = Array.new
6
+ return screens unless self.has_key?('screens')
7
+ return screens unless self['screens'].class == Hash
8
+
9
+ screens = self['screens'].keys
10
+ return screens
11
+ end
12
+
13
+ def screen_exists?(screen_name)
14
+ return self.get_screens.include?(screen_name)
15
+ end
16
+
17
+ def view_has_modal?(view_name, modal_name)
18
+ return false unless self.view_exists?(view_name)
19
+
20
+ view_configuration = self['views'][view_name]
21
+ return self.get_modals(view_configuration).include?(modal_name)
22
+ end
23
+
24
+ def get_view_modals(view_name)
25
+ modals = Array.new
26
+ return modals unless self.has_key?('views')
27
+ return modals unless self['views'].class == Hash
28
+ return modals unless self['views'].has_key?(view_name)
29
+
30
+ view_configuration = self['views'][view_name]
31
+ return self.get_modals(view_configuration)
32
+ end
33
+
34
+ def screen_has_modal?(screen_name, modal_name)
35
+ return false unless self.screen_exists?(screen_name)
36
+
37
+ screen_configuration = self['screens'][screen_name]
38
+ return self.get_modals(screen_configuration).include?(modal_name)
39
+ end
40
+
41
+ def get_screen_modals(screen_name)
42
+ modals = Array.new
43
+ return modals unless self.has_key?('screens')
44
+ return modals unless self['screens'].class == Hash
45
+ return modals unless self['screens'].has_key?(screen_name)
46
+
47
+ screen_configuration = self['screens'][screen_name]
48
+ return self.get_modals(screen_configuration)
49
+ end
50
+
51
+ def get_modals(configuration)
52
+ modals = Array.new
53
+
54
+ return modals unless configuration.class == Hash
55
+ return modals unless configuration.has_key?('modals')
56
+ return modals unless configuration['modals'].class == Hash
57
+
58
+ modals = configuration['modals'].keys
59
+ return modals
60
+ end
61
+
62
+ def screen_has_live?(screen_name)
63
+ return false unless self.screen_exists?(screen_name)
64
+
65
+ screen_configuration = self['screens'][screen_name]
66
+ return false unless screen_configuration.class == Hash
67
+
68
+ if screen_configuration.has_key?('live?')
69
+ return true if screen_configuration['live?'].class == Hash
70
+ return false
71
+ end
72
+
73
+ #Check if has views
74
+ return false unless screen_configuration.has_key?('included_views')
75
+ return false unless screen_configuration['included_views'].class == Array
76
+
77
+ #No need to check if views doesn't exit
78
+ return false unless self.has_key?('views')
79
+ return false unless self['views'].class == Hash
80
+
81
+ screen_configuration['included_views'].each { |included_view|
82
+ return false unless self['views'].has_key?(included_view)
83
+ return false unless self['views'][included_view].class == Hash
84
+
85
+ view_configuration = self['views'][included_view]
86
+ return true if view_configuration.has_key?('live?') and view_configuration['live?'].class == Hash
87
+ }
88
+
89
+ return false
90
+ end
91
+
92
+ def view_exists?(view_name)
93
+ return self.get_views.include?(view_name)
94
+ end
95
+
96
+ def get_views
97
+ views = Array.new
98
+ return views unless self.has_key?('views')
99
+ return views unless self['views'].class == Hash
100
+
101
+ views = self['views'].keys
102
+ return views
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,198 @@
1
+ module AutomationObject
2
+ module BluePrintValidation
3
+ module ElementValidation
4
+ def validate_elements
5
+ error_messages = Array.new
6
+
7
+ elements = self.get_elements
8
+
9
+ elements.each { |element|
10
+ #Set level string and get it out of the way
11
+ level_key_string = ''
12
+ if element[:view_name]
13
+ level_key_string = "(views/#{element[:view_name]}/elements)"
14
+ elsif element[:modal_name]
15
+ level_key_string = "(screens/#{element[:screen_name]}/modals/#{element[:modal_name]}/elements)"
16
+ else
17
+ level_key_string = "(screens/#{element[:screen_name]}/elements)"
18
+ end
19
+
20
+ unless element[:element_name].is_a?(String)
21
+ error_message = "#{level_key_string} level key (#{element[:element_name]}) is an invalid key type, expecting: ("
22
+ error_message << String.to_s
23
+ error_message << "), got: (#{element[:element_name].class.to_s})"
24
+ error_messages.push(FormattedErrors::format_message(error_message))
25
+ end
26
+
27
+ #Skip checking if nil, being nice
28
+ next if element[:configuration] == nil
29
+
30
+ unless element[:configuration].is_a?(Hash)
31
+ error_message = "#{level_key_string} level key (#{element[:element_name]}) is an invalid value type, expecting: ("
32
+ error_message << Hash.to_s
33
+ error_message << "), got: (#{element[:configuration].class.to_s})"
34
+ error_messages.push(FormattedErrors::format_message(error_message))
35
+
36
+ next #Skip any additional validation on this
37
+ end
38
+
39
+ element[:configuration].each { |sub_element_key, sub_element_value|
40
+ #Check if valid element keys
41
+ unless KeyValueConstants::ELEMENT_PAIR_TYPES.keys.include?(sub_element_key)
42
+ error_message = "#{level_key_string} level key (#{element[:element_name]}) sub key (#{sub_element_key}) "
43
+ error_message << 'is not a valid key, available (elements) sub level keys ('
44
+ error_message << KeyValueConstants::ELEMENT_PAIR_TYPES.keys.join(', ').to_s + ')'
45
+ error_messages.push(FormattedErrors::format_message(error_message))
46
+
47
+ next #skip if not a valid key since we are not going to check value
48
+ end
49
+
50
+ #Skip checking if nil, being nice
51
+ next if sub_element_value == nil
52
+
53
+ #Check sub element value
54
+ unless sub_element_value.is_a?(KeyValueConstants::ELEMENT_PAIR_TYPES[sub_element_key])
55
+ error_message = "#{level_key_string} level key (#{element[:element_name]}) sub key (#{sub_element_key}) "
56
+ error_message << 'has an invalid value type, expected: ('
57
+ error_message << KeyValueConstants::SCREEN_PAIR_TYPES[sub_element_key].to_s
58
+ error_message << "), got: (#{sub_element_value.class.to_s})"
59
+ error_messages.push(FormattedErrors::format_message(error_message))
60
+
61
+ next #Skip any additional validation on this
62
+ end
63
+
64
+ case sub_element_key
65
+ when 'define_elements_by'
66
+ valid_element_methods = KeyValueConstants::ELEMENT_KEYS + self.get_element_custom_methods(element[:configuration])
67
+
68
+ unless valid_element_methods.include?(sub_element_value)
69
+ error_message = "#{level_key_string} level key (#{element[:element_name]}) sub key (#{sub_element_key}) "
70
+ error_message << 'is not a valid element methods key. Available keys ('
71
+ error_message << valid_element_methods.join(', ')
72
+ error_message << ')'
73
+ error_messages.push(FormattedErrors::format_message(error_message))
74
+ end
75
+ when 'custom_methods'
76
+ sub_element_value.each { |custom_method_name, custom_method_configuration|
77
+ unless custom_method_name.is_a?(String)
78
+ error_message = "#{level_key_string} level key (#{element[:element_name]}) custom_methods sub key (#{custom_method_name}) "
79
+ error_message << 'is not a valid key type, expected: ('
80
+ error_message << String.to_s
81
+ error_message << "), got: (#{custom_method_name.class.to_s})"
82
+ error_messages.push(FormattedErrors::format_message(error_message))
83
+ end
84
+
85
+ unless custom_method_configuration.is_a?(Hash)
86
+ error_message = "#{level_key_string} level key (#{element[:element_name]}) custom_methods sub key (#{custom_method_name}) "
87
+ error_message << 'is not a valid key value type, expected: ('
88
+ error_message << Hash.to_s
89
+ error_message << "), got: (#{custom_method_configuration.class.to_s})"
90
+ error_messages.push(FormattedErrors::format_message(error_message))
91
+
92
+ next
93
+ end
94
+
95
+ custom_method_configuration.each { |custom_method_key, custom_method_value|
96
+ unless KeyValueConstants::ELEMENT_CUSTOM_METHOD_PAIR_TYPES.keys.include?(custom_method_key)
97
+ error_message = "#{level_key_string} level key (#{element[:element_name]}) custom_methods (#{custom_method_name}) method sub key (#{custom_method_key}) "
98
+ error_message << 'is not a valid key, available (custom_methods) sub level keys ('
99
+ error_message << KeyValueConstants::ELEMENT_CUSTOM_METHOD_PAIR_TYPES.keys.join(', ').to_s + ')'
100
+ error_messages.push(FormattedErrors::format_message(error_message))
101
+
102
+ next #skip if not a valid key since we are not going to check value
103
+ end
104
+
105
+ #Skip checking if nil, being nice
106
+ next if custom_method_value == nil
107
+
108
+ unless custom_method_value.is_a?(KeyValueConstants::ELEMENT_CUSTOM_METHOD_PAIR_TYPES[custom_method_key])
109
+ error_message = "#{level_key_string} level key (#{element[:element_name]}) custom_methods (#{custom_method_name}) method sub key (#{custom_method_key}) "
110
+ error_message << 'has an invalid value type, expected: ('
111
+ error_message << KeyValueConstants::ELEMENT_CUSTOM_METHOD_PAIR_TYPES[custom_method_key].to_s
112
+ error_message << "), got: (#{custom_method_value.class.to_s})"
113
+ error_messages.push(FormattedErrors::format_message(error_message))
114
+
115
+ next #Skip any additional validation on this
116
+ end
117
+
118
+ case custom_method_key
119
+ when 'element_method'
120
+ unless KeyValueConstants::ELEMENT_KEYS.include?(custom_method_value)
121
+ error_message = "#{level_key_string} level key (#{element[:element_name]}) custom_methods (#{custom_method_name}) sub key (#{custom_method_key}) "
122
+ error_message << 'is not a valid elements method. Available element methods ('
123
+ error_message << KeyValueConstants::ELEMENT_KEYS.join(', ')
124
+ error_messages.push(FormattedErrors::format_message(error_message))
125
+ end
126
+ end
127
+ }
128
+ }
129
+ end
130
+ }
131
+ }
132
+
133
+ return error_messages
134
+ end
135
+
136
+ def get_element_custom_methods(configuration)
137
+ custom_methods = Array.new
138
+ return custom_methods unless configuration.class == Hash
139
+ return custom_methods unless configuration.has_key?('custom_methods')
140
+ return custom_methods unless configuration['custom_methods'].class == Hash
141
+
142
+ custom_methods = configuration['custom_methods'].keys
143
+ return custom_methods
144
+ end
145
+
146
+ def get_elements
147
+ elements = Array.new
148
+
149
+ if self.has_key?('views') and self['views'].class == Hash
150
+ self['views'].each { |view_name, view_configuration|
151
+ next unless view_configuration.class == Hash
152
+ next unless view_configuration.has_key?('elements')
153
+ next unless view_configuration['elements'].class == Hash
154
+
155
+ view_configuration['elements'].each { |view_element_name, view_element_configuration|
156
+ element = {:view_name => view_name, :element_name => view_element_name,
157
+ :configuration => view_element_configuration}
158
+ elements.push(element)
159
+ }
160
+ }
161
+ end
162
+
163
+ if self.has_key?('screens') and self['screens'].class == Hash
164
+ self['screens'].each { |screen_name, screen_configuration|
165
+ next unless screen_configuration.class == Hash
166
+
167
+ if screen_configuration.has_key?('elements') and screen_configuration['elements'].class == Hash
168
+ screen_configuration['elements'].each { |screen_element_name, screen_element_configuration|
169
+ element = {:screen_name => screen_name, :element_name => screen_element_name,
170
+ :configuration => screen_element_configuration}
171
+ elements.push(element)
172
+ }
173
+ end
174
+
175
+ #Get elements from modals
176
+ next unless screen_configuration.class == Hash
177
+ next unless screen_configuration.has_key?('modals')
178
+ next unless screen_configuration['modals'].class == Hash
179
+
180
+ screen_configuration['modals'].each { |modal_name, modal_configuration|
181
+ next unless modal_configuration.class == Hash
182
+ next unless modal_configuration.has_key?('elements')
183
+ next unless modal_configuration['elements'].class == Hash
184
+
185
+ modal_configuration['elements'].each { |modal_element_name, modal_element_configuration|
186
+ element = {:screen_name => screen_name, :modal_name => modal_name,
187
+ :element_name => modal_element_name, :configuration => modal_element_configuration}
188
+ elements.push(element)
189
+ }
190
+ }
191
+ }
192
+ end
193
+
194
+ return elements
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,41 @@
1
+ module AutomationObject
2
+ module BluePrintValidation
3
+ class FormattedErrors
4
+ MESSAGE_COLOR = :red
5
+ SPECIFIC_VALUE_COLOR = :blue
6
+
7
+ def self.array_to_message(error_messages)
8
+ error_messages.each_with_index { |raw_message, index|
9
+ error_messages[index] = (((index+1).to_s + '. ').colorize(MESSAGE_COLOR) + raw_message)
10
+ error_messages[index] = "\n" + error_messages[index] if index == 0
11
+ }
12
+
13
+ formatted_message = error_messages.join("\n ----- \n")
14
+ formatted_message << "\n ----- \n"
15
+ return formatted_message
16
+ end
17
+
18
+ def self.format_message(error_message)
19
+ specific_values = error_message.scan(/\([^\)]+\)/)
20
+ replaced_string = error_message.gsub(/\([^\)]+\)/, '######')
21
+ message_array = replaced_string.split('######')
22
+
23
+ return error_message.colorize(MESSAGE_COLOR) if specific_values.length == 0
24
+
25
+ formatted_message = ''
26
+ message_array.each_with_index { |message, index|
27
+ formatted_message << message.colorize(MESSAGE_COLOR)
28
+
29
+ next if specific_values[index] == nil
30
+ stripped_specific_value = specific_values[index].gsub(/\(/, '').gsub(/\)/, '')
31
+ final_specific_value = '('.colorize(MESSAGE_COLOR)
32
+ final_specific_value << stripped_specific_value.colorize(SPECIFIC_VALUE_COLOR)
33
+ final_specific_value << ')'.colorize(MESSAGE_COLOR)
34
+ formatted_message << final_specific_value
35
+ }
36
+
37
+ return formatted_message
38
+ end
39
+ end
40
+ end
41
+ end