testcentricity 2.3.13

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +6 -0
  7. data/Gemfile.lock +93 -0
  8. data/LICENSE.txt +28 -0
  9. data/README.md +1634 -0
  10. data/Rakefile +1 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/lib/devices/devices.yml +344 -0
  14. data/lib/testcentricity.rb +144 -0
  15. data/lib/testcentricity/app_core/appium_connect_helper.rb +154 -0
  16. data/lib/testcentricity/app_core/appium_server.rb +69 -0
  17. data/lib/testcentricity/app_core/screen_objects_helper.rb +180 -0
  18. data/lib/testcentricity/app_core/screen_sections_helper.rb +332 -0
  19. data/lib/testcentricity/app_elements/app_element_helper.rb +293 -0
  20. data/lib/testcentricity/app_elements/button.rb +8 -0
  21. data/lib/testcentricity/app_elements/checkbox.rb +20 -0
  22. data/lib/testcentricity/app_elements/label.rb +8 -0
  23. data/lib/testcentricity/app_elements/list.rb +25 -0
  24. data/lib/testcentricity/app_elements/switch.rb +20 -0
  25. data/lib/testcentricity/app_elements/textfield.rb +12 -0
  26. data/lib/testcentricity/browser_helper.rb +174 -0
  27. data/lib/testcentricity/data_objects/data_objects_helper.rb +78 -0
  28. data/lib/testcentricity/data_objects/environment.rb +281 -0
  29. data/lib/testcentricity/data_objects/excel_helper.rb +242 -0
  30. data/lib/testcentricity/exception_queue_helper.rb +51 -0
  31. data/lib/testcentricity/utility_helpers.rb +28 -0
  32. data/lib/testcentricity/version.rb +3 -0
  33. data/lib/testcentricity/web_core/drag_drop_helper.rb +15 -0
  34. data/lib/testcentricity/web_core/page_objects_helper.rb +669 -0
  35. data/lib/testcentricity/web_core/page_sections_helper.rb +866 -0
  36. data/lib/testcentricity/web_core/webdriver_helper.rb +579 -0
  37. data/lib/testcentricity/web_elements/button.rb +8 -0
  38. data/lib/testcentricity/web_elements/cell_button.rb +8 -0
  39. data/lib/testcentricity/web_elements/cell_checkbox.rb +38 -0
  40. data/lib/testcentricity/web_elements/cell_element.rb +69 -0
  41. data/lib/testcentricity/web_elements/cell_image.rb +8 -0
  42. data/lib/testcentricity/web_elements/cell_radio.rb +31 -0
  43. data/lib/testcentricity/web_elements/checkbox.rb +100 -0
  44. data/lib/testcentricity/web_elements/file_field.rb +45 -0
  45. data/lib/testcentricity/web_elements/image.rb +34 -0
  46. data/lib/testcentricity/web_elements/label.rb +8 -0
  47. data/lib/testcentricity/web_elements/link.rb +8 -0
  48. data/lib/testcentricity/web_elements/list.rb +73 -0
  49. data/lib/testcentricity/web_elements/list_button.rb +8 -0
  50. data/lib/testcentricity/web_elements/list_checkbox.rb +38 -0
  51. data/lib/testcentricity/web_elements/list_element.rb +61 -0
  52. data/lib/testcentricity/web_elements/list_radio.rb +31 -0
  53. data/lib/testcentricity/web_elements/radio.rb +74 -0
  54. data/lib/testcentricity/web_elements/select_list.rb +197 -0
  55. data/lib/testcentricity/web_elements/siebel_open_ui_helper.rb +15 -0
  56. data/lib/testcentricity/web_elements/table.rb +612 -0
  57. data/lib/testcentricity/web_elements/textfield.rb +114 -0
  58. data/lib/testcentricity/web_elements/ui_elements_helper.rb +502 -0
  59. data/lib/testcentricity/world_extensions.rb +26 -0
  60. data/my_templates/default/method_details/setup.rb +3 -0
  61. data/spec/spec_helper.rb +14 -0
  62. data/spec/testcentricity_spec.rb +9 -0
  63. data/testcentricity.gemspec +47 -0
  64. metadata +328 -0
@@ -0,0 +1,154 @@
1
+ require 'appium_lib'
2
+
3
+
4
+ module TestCentricity
5
+ module AppiumConnect
6
+
7
+ attr_accessor :running
8
+ attr_accessor :config_file
9
+
10
+ def self.initialize_appium(project_path = nil)
11
+ Environ.platform = :mobile
12
+ Environ.driver = :appium
13
+ Environ.device_type = ENV['DEVICE_TYPE'] if ENV['DEVICE_TYPE']
14
+
15
+ @config_file = project_path
16
+
17
+ if project_path.nil?
18
+ Environ.device_name = ENV['APP_DEVICE']
19
+ Environ.device_os = ENV['APP_PLATFORM_NAME']
20
+ Environ.device_orientation = ENV['ORIENTATION'] if ENV['ORIENTATION']
21
+ if ENV['UDID']
22
+ Environ.device = :device
23
+ else
24
+ Environ.device = :simulator
25
+ end
26
+ end
27
+ @running = false
28
+ end
29
+
30
+ def self.start_driver
31
+ if @config_file.nil?
32
+ desired_capabilities = {
33
+ caps: {
34
+ platformName: ENV['APP_PLATFORM_NAME'],
35
+ platformVersion: ENV['APP_VERSION'],
36
+ deviceName: ENV['APP_DEVICE'],
37
+ automationName: ENV['AUTOMATION_ENGINE']
38
+ }
39
+ }
40
+ capabilities = desired_capabilities[:caps]
41
+ capabilities[:avd] = ENV['APP_DEVICE'] if ENV['APP_PLATFORM_NAME'].downcase.to_sym == :android
42
+ capabilities[:orientation] = ENV['ORIENTATION'].upcase if ENV['ORIENTATION']
43
+ capabilities[:language] = ENV['LANGUAGE'] if ENV['LANGUAGE']
44
+ capabilities[:locale] = ENV['LOCALE'].gsub('-', '_') if ENV['LOCALE']
45
+ capabilities[:newCommandTimeout] = ENV['NEW_COMMAND_TIMEOUT'] if ENV['NEW_COMMAND_TIMEOUT']
46
+ capabilities[:noReset] = ENV['APP_NO_RESET'] if ENV['APP_NO_RESET']
47
+ capabilities[:fullReset] = ENV['APP_FULL_RESET'] if ENV['APP_FULL_RESET']
48
+ if ENV['UDID']
49
+ capabilities[:udid] = ENV['UDID']
50
+ capabilities[:bundleId] = ENV['BUNDLE_ID'] if ENV['BUNDLE_ID']
51
+ capabilities[:xcodeOrgId] = ENV['TEAM_ID'] if ENV['TEAM_ID']
52
+ capabilities[:xcodeSigningId] = ENV['TEAM_NAME'] if ENV['TEAM_NAME']
53
+ capabilities[:appActivity] = ENV['APP_ACTIVITY'] if ENV['APP_ACTIVITY']
54
+ capabilities[:appPackage] = ENV['APP_PACKAGE'] if ENV['APP_PACKAGE']
55
+ end
56
+
57
+ if ENV['APP']
58
+ capabilities[:app] = ENV['APP']
59
+ else
60
+ if Environ.is_android?
61
+ capabilities[:app] = Environ.current.android_apk_path
62
+ elsif Environ.is_ios?
63
+ if Environ.is_device?
64
+ capabilities[:app] = Environ.current.ios_ipa_path
65
+ else
66
+ capabilities[:app] = Environ.current.ios_app_path
67
+ end
68
+ end
69
+ end
70
+
71
+ else
72
+ base_path = 'config'
73
+ unless File.directory?(File.join(@config_file, base_path))
74
+ raise 'Could not find appium.txt files in /config folder'
75
+ end
76
+ appium_caps = File.join(@config_file, base_path, 'appium.txt')
77
+ desired_capabilities = Appium.load_appium_txt file: appium_caps
78
+ end
79
+ Appium::Driver.new(desired_capabilities).start_driver
80
+ @running = true
81
+ Appium.promote_appium_methods TestCentricity::ScreenObject
82
+ Appium.promote_appium_methods TestCentricity::AppUIElement
83
+ end
84
+
85
+ def self.quit_driver
86
+ if @running
87
+ $driver.driver_quit
88
+ @running = false
89
+ end
90
+ end
91
+
92
+ def self.driver
93
+ $driver
94
+ end
95
+
96
+ def self.take_screenshot(png_save_path)
97
+ FileUtils.mkdir_p(File.dirname(png_save_path))
98
+ $driver.driver.save_screenshot(png_save_path)
99
+ end
100
+
101
+ def self.install_app(app_path)
102
+ $driver.install_app(app_path)
103
+ end
104
+
105
+ def self.app_installed?(bundle_id)
106
+ $driver.app_installed?(bundle_id)
107
+ end
108
+
109
+ def self.launch_app
110
+ $driver.launch_app
111
+ end
112
+
113
+ def self.close_app
114
+ $driver.close_app
115
+ end
116
+
117
+ def self.reset_app
118
+ $driver.reset
119
+ end
120
+
121
+ def self.remove_app(bundle_id)
122
+ $driver.remove_app(bundle_id)
123
+ end
124
+
125
+ def self.implicit_wait(timeout)
126
+ $driver.manage.timeouts.implicit_wait = timeout
127
+ end
128
+
129
+ def self.hide_keyboard
130
+ $driver.hide_keyboard
131
+ end
132
+
133
+ def self.keyboard_shown?
134
+ $driver.is_keyboard_shown
135
+ end
136
+
137
+ def self.set_geolocation(latitude, longitude, altitude)
138
+ $driver.set_location(latitude, longitude, altitude)
139
+ end
140
+
141
+ def self.current_context
142
+ $driver.current_context
143
+ end
144
+
145
+ def self.set_context(context)
146
+ $driver.set_context(context)
147
+ end
148
+
149
+ def self.available_contexts
150
+ $driver.available_contexts
151
+ end
152
+ end
153
+ end
154
+
@@ -0,0 +1,69 @@
1
+ require 'childprocess'
2
+
3
+ #
4
+ # This class is designed to start and stop the Appium Server process. In order to use it you must have Appium
5
+ # and node installed on your computer. You can pass parameters to Appium at startup via the constructor.
6
+ #
7
+ module TestCentricity
8
+ class AppiumServer
9
+
10
+ attr_accessor :process
11
+
12
+ def initialize(params={})
13
+ @params = params
14
+ end
15
+
16
+ #
17
+ # Start the Appium Server
18
+ #
19
+ def start
20
+ # terminate any currently running Appium Server
21
+ if running?
22
+ system('killall -9 node')
23
+ puts 'Terminating existing Appium Server'
24
+ sleep(5)
25
+ puts 'Appium Server is being restarted'
26
+ else
27
+ puts 'Appium Server is being started'
28
+ end
29
+ # start new Appium Server
30
+ @process = ChildProcess.build(*parameters)
31
+ process.start
32
+ # wait until confirmation that Appium Server is running
33
+ wait = Selenium::WebDriver::Wait.new(timeout: 30)
34
+ wait.until { running? }
35
+ puts "Appium Server is running - PID = #{process.pid}"
36
+ end
37
+
38
+ #
39
+ # Check to see if Appium Server is running
40
+ #
41
+ def running?
42
+ response = nil
43
+ begin
44
+ response = Net::HTTP.get_response(URI('http://127.0.0.1:4723/wd/hub/sessions'))
45
+ rescue
46
+ end
47
+ response && response.code_type == Net::HTTPOK
48
+ end
49
+
50
+ #
51
+ # Stop the Appium Server
52
+ #
53
+ def stop
54
+ process.stop
55
+ puts 'Appium Server has been terminated'
56
+ end
57
+
58
+ private
59
+
60
+ def parameters
61
+ cmd = ['appium']
62
+ @params.each do |key, value|
63
+ cmd << '--' + key.to_s
64
+ cmd << value.to_s if not value.nil? and value.size > 0
65
+ end
66
+ cmd
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,180 @@
1
+ require 'test/unit'
2
+
3
+ module TestCentricity
4
+ class ScreenObject
5
+ include Test::Unit::Assertions
6
+
7
+ attr_reader :strategy, :locator
8
+
9
+ def initialize
10
+ raise "Screen object #{self.class.name} does not have a page_locator trait defined" unless defined?(page_locator)
11
+ @strategy = page_locator[0].to_sym
12
+ @locator = page_locator[1]
13
+ end
14
+
15
+ def self.trait(trait_name, &block)
16
+ define_method(trait_name.to_s, &block)
17
+ end
18
+
19
+ def self.element(element_name, strategy, locator)
20
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppUIElement.new("#{element_name}", self, "#{strategy}", "#{locator}", :page);end))
21
+ end
22
+
23
+ def self.button(element_name, strategy, locator)
24
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppButton.new("#{element_name}", self, "#{strategy}", "#{locator}", :page);end))
25
+ end
26
+
27
+ def self.textfield(element_name, strategy, locator)
28
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppTextField.new("#{element_name}", self, "#{strategy}", "#{locator}", :page);end))
29
+ end
30
+
31
+ def self.switch(element_name, strategy, locator)
32
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppSwitch.new("#{element_name}", self, "#{strategy}", "#{locator}", :page);end))
33
+ end
34
+
35
+ def self.checkbox(element_name, strategy, locator)
36
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppCheckBox.new("#{element_name}", self, "#{strategy}", "#{locator}", :page);end))
37
+ end
38
+
39
+ def self.label(element_name, strategy, locator)
40
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppLabel.new("#{element_name}", self, "#{strategy}", "#{locator}", :page);end))
41
+ end
42
+
43
+ def self.list(element_name, strategy, locator)
44
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppList.new("#{element_name}", self, "#{strategy}", "#{locator}", :page);end))
45
+ end
46
+
47
+ def self.section(section_name, class_name)
48
+ class_eval(%(def #{section_name};@#{section_name} ||= #{class_name}.new("#{section_name}", self, :page);end))
49
+ end
50
+
51
+ def open_portal
52
+ environment = Environ.current
53
+
54
+ Environ.portal_state = :open
55
+ end
56
+
57
+ def verify_page_exists
58
+ wait = Selenium::WebDriver::Wait.new(timeout: Environ.default_max_wait_time)
59
+ wait.until { $driver.find_element(@strategy.to_sym, @locator).displayed? }
60
+ PageManager.current_page = self
61
+ rescue
62
+ raise "Could not find page_locator for screen object '#{self.class.name}' (:#{@strategy}, #{@locator}) after #{Environ.default_max_wait_time} seconds"
63
+ end
64
+
65
+ def navigate_to; end
66
+
67
+ def verify_page_ui; end
68
+
69
+ def load_page
70
+ verify_page_exists
71
+ PageManager.current_page = self
72
+ end
73
+
74
+
75
+
76
+ def verify_ui_states(ui_states)
77
+ ui_states.each do |ui_object, object_states|
78
+ object_states.each do |property, state|
79
+
80
+
81
+ puts "#{ui_object.get_name} - #{property} = #{state}" if ENV['DEBUG']
82
+
83
+
84
+ case property
85
+ when :exists
86
+ actual = ui_object.exists?
87
+ when :enabled
88
+ actual = ui_object.enabled?
89
+ when :disabled
90
+ actual = ui_object.disabled?
91
+ when :visible
92
+ actual = ui_object.visible?
93
+ when :hidden
94
+ actual = ui_object.hidden?
95
+ when :checked
96
+ actual = ui_object.checked?
97
+ when :selected
98
+ actual = ui_object.selected?
99
+ when :value
100
+ actual = ui_object.get_value
101
+ when :caption
102
+ actual = ui_object.get_caption
103
+ when :name
104
+ actual = ui_object.tag_name
105
+ when :placeholder
106
+ actual = ui_object.get_placeholder
107
+ when :items
108
+ actual = ui_object.get_list_items
109
+ when :itemcount
110
+ actual = ui_object.get_item_count
111
+ end
112
+
113
+ if state.is_a?(Hash) && state.length == 1
114
+ error_msg = "Expected UI object '#{ui_object.get_name}' (#{ui_object.get_locator}) #{property} property to"
115
+ state.each do |key, value|
116
+ case key
117
+ when :lt, :less_than
118
+ ExceptionQueue.enqueue_exception("#{error_msg} be less than #{value} but found '#{actual}'") unless actual < value
119
+ when :lt_eq, :less_than_or_equal
120
+ ExceptionQueue.enqueue_exception("#{error_msg} be less than or equal to #{value} but found '#{actual}'") unless actual <= value
121
+ when :gt, :greater_than
122
+ ExceptionQueue.enqueue_exception("#{error_msg} be greater than #{value} but found '#{actual}'") unless actual > value
123
+ when :gt_eq, :greater_than_or_equal
124
+ ExceptionQueue.enqueue_exception("#{error_msg} be greater than or equal to #{value} but found '#{actual}'") unless actual >= value
125
+ when :starts_with
126
+ ExceptionQueue.enqueue_exception("#{error_msg} start with '#{value}' but found '#{actual}'") unless actual.start_with?(value)
127
+ when :ends_with
128
+ ExceptionQueue.enqueue_exception("#{error_msg} end with '#{value}' but found '#{actual}'") unless actual.end_with?(value)
129
+ when :contains
130
+ ExceptionQueue.enqueue_exception("#{error_msg} contain '#{value}' but found '#{actual}'") unless actual.include?(value)
131
+ when :not_contains, :does_not_contain
132
+ ExceptionQueue.enqueue_exception("#{error_msg} not contain '#{value}' but found '#{actual}'") if actual.include?(value)
133
+ when :not_equal
134
+ ExceptionQueue.enqueue_exception("#{error_msg} not equal '#{value}' but found '#{actual}'") if actual == value
135
+ when :like, :is_like
136
+ actual_like = actual.delete("\n")
137
+ actual_like = actual_like.delete("\r")
138
+ actual_like = actual_like.delete("\t")
139
+ actual_like = actual_like.delete(' ')
140
+ actual_like = actual_like.downcase
141
+ expected = value.delete("\n")
142
+ expected = expected.delete("\r")
143
+ expected = expected.delete("\t")
144
+ expected = expected.delete(' ')
145
+ expected = expected.downcase
146
+ ExceptionQueue.enqueue_exception("#{error_msg} be like '#{value}' but found '#{actual}'") unless actual_like.include?(expected)
147
+ when :translate
148
+ expected = I18n.t(value)
149
+ ExceptionQueue.enqueue_assert_equal(expected, actual, "Expected UI object '#{ui_object.get_name}' (#{ui_object.get_locator}) translated #{property} property")
150
+ end
151
+ end
152
+ else
153
+ ExceptionQueue.enqueue_assert_equal(state, actual, "Expected UI object '#{ui_object.get_name}' (#{ui_object.get_locator}) #{property} property")
154
+ end
155
+ end
156
+ end
157
+ ExceptionQueue.post_exceptions
158
+ end
159
+
160
+ def populate_data_fields(data, wait_time = nil)
161
+ timeout = wait_time.nil? ? 5 : wait_time
162
+ data.each do |data_field, data_param|
163
+ unless data_param.blank?
164
+ # make sure the intended UI target element is visible before trying to set its value
165
+ data_field.wait_until_visible(timeout)
166
+ if data_param == '!DELETE'
167
+ data_field.clear
168
+ else
169
+ case data_field.get_object_type
170
+ when :checkbox
171
+ data_field.set_checkbox_state(data_param.to_bool)
172
+ when :textfield
173
+ data_field.set("#{data_param}\t")
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,332 @@
1
+ require 'test/unit'
2
+
3
+ module TestCentricity
4
+ class ScreenSection
5
+ include Test::Unit::Assertions
6
+
7
+ attr_reader :context, :name
8
+ attr_accessor :locator
9
+ attr_accessor :parent
10
+ attr_accessor :strategy
11
+ attr_accessor :parent_list
12
+ attr_accessor :list_index
13
+
14
+ def initialize(name, parent, context)
15
+ @name = name
16
+ @parent = parent
17
+ @context = context
18
+ @parent_list = nil
19
+ @list_index = nil
20
+ @strategy = nil
21
+ @locator = nil
22
+ end
23
+
24
+ def get_locator
25
+ if @locator.nil? && defined?(section_locator)
26
+ @strategy = section_locator[0]
27
+ @locator = section_locator[1]
28
+ end
29
+
30
+ locators = []
31
+ if @context == :section && !@parent.nil?
32
+ parent_strategy, parent_locator = @parent.get_locator
33
+ end
34
+
35
+ if @parent_list.nil?
36
+ if parent_strategy == @strategy
37
+ locators.push([@strategy, @locator])
38
+ else
39
+ locators.push([parent_strategy, parent_locator]) unless parent_strategy.nil?
40
+ locators.push([@strategy, "#{parent_locator}#{@locator}"])
41
+ end
42
+ else
43
+ list_strategy, list_locator = @parent_list.get_locator
44
+ if parent_strategy == list_strategy
45
+ list_locator = "#{parent_locator}#{list_locator}"
46
+ else
47
+ locators.push([parent_strategy, parent_locator]) unless parent_strategy.nil?
48
+ end
49
+ if list_strategy == @strategy
50
+ obj_locator = "#{list_locator}#{@locator}"
51
+ else
52
+ obj_locator = @locator
53
+ locators.push([list_strategy, list_locator])
54
+ end
55
+ unless @list_index.nil?
56
+ obj_locator = "#{obj_locator}[#{@list_index}]"
57
+ end
58
+ locators.push([@strategy, obj_locator])
59
+ end
60
+ locators
61
+ end
62
+
63
+
64
+ def set_list_index(list, index = 1)
65
+ @parent_list = list unless list.nil?
66
+ @list_index = index
67
+ end
68
+
69
+ def get_item_count
70
+ raise 'No parent list defined' if @parent_list.nil?
71
+ @parent_list.get_item_count
72
+ end
73
+
74
+ def get_list_items
75
+ items = []
76
+ (1..get_item_count).each do |item|
77
+ set_list_index(nil, item)
78
+ items.push(get_value)
79
+ end
80
+ items
81
+ end
82
+
83
+ def get_object_type
84
+ :section
85
+ end
86
+
87
+ def get_name
88
+ @name
89
+ end
90
+
91
+ def set_parent(parent)
92
+ @parent = parent
93
+ end
94
+
95
+
96
+ def self.trait(trait_name, &block)
97
+ define_method(trait_name.to_s, &block)
98
+ end
99
+
100
+ def self.element(element_name, strategy, locator)
101
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppUIElement.new("#{element_name}", self, "#{strategy}", "#{locator}", :section);end))
102
+ end
103
+
104
+ def self.button(element_name, strategy, locator)
105
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppButton.new("#{element_name}", self, "#{strategy}", "#{locator}", :section);end))
106
+ end
107
+
108
+ def self.textfield(element_name, strategy, locator)
109
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppTextField.new("#{element_name}", self, "#{strategy}", "#{locator}", :section);end))
110
+ end
111
+
112
+ def self.switch(element_name, strategy, locator)
113
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppSwitch.new("#{element_name}", self, "#{strategy}", "#{locator}", :section);end))
114
+ end
115
+
116
+ def self.checkbox(element_name, strategy, locator)
117
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppCheckBox.new("#{element_name}", self, "#{strategy}", "#{locator}", :section);end))
118
+ end
119
+
120
+ def self.label(element_name, strategy, locator)
121
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppLabel.new("#{element_name}", self, "#{strategy}", "#{locator}", :section);end))
122
+ end
123
+
124
+ def self.list(element_name, strategy, locator)
125
+ class_eval(%(def #{element_name};@#{element_name} ||= TestCentricity::AppList.new("#{element_name}", self, "#{strategy}", "#{locator}", :section);end))
126
+ end
127
+
128
+ def self.section(section_name, class_name)
129
+ class_eval(%(def #{section_name};@#{section_name} ||= #{class_name}.new("#{section_name}", self, :section);end))
130
+ end
131
+
132
+
133
+
134
+ def click
135
+ section = find_section
136
+ raise "Section object '#{get_name}' (#{get_locator}) not found" unless section
137
+ section.click
138
+ end
139
+
140
+ def tap
141
+ section = find_section
142
+ raise "Section object '#{get_name}' (#{get_locator}) not found" unless section
143
+ x = section.location.x
144
+ y = section.location.y
145
+ tap_action = Appium::TouchAction.new.tap(element: section, x: x, y: y)
146
+ tap_action.perform
147
+ end
148
+
149
+ def double_tap
150
+ section = find_section
151
+ raise "Section object '#{get_name}' (#{get_locator}) not found" unless section
152
+ x = section.location.x
153
+ y = section.location.y
154
+ tap_action = Appium::TouchAction.new.double_tap(element: section, x: x, y: y)
155
+ tap_action.perform
156
+ end
157
+
158
+ def exists?
159
+ section = find_section
160
+ section != nil
161
+ end
162
+
163
+ def enabled?
164
+ section = find_section
165
+ raise "Section object '#{get_name}' (#{get_locator}) not found" unless section
166
+ section.enabled?
167
+ end
168
+
169
+ def disabled?
170
+ section = find_section
171
+ raise "Section object '#{get_name}' (#{get_locator}) not found" unless section
172
+ section.enabled?
173
+ end
174
+
175
+ def visible?
176
+ if exists?
177
+ section.displayed?
178
+ else
179
+ false
180
+ end
181
+ end
182
+
183
+ def hidden?
184
+ !visible?
185
+ end
186
+
187
+ def wait_until_exists(seconds = nil)
188
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
189
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
190
+ wait.until { exists? }
191
+ rescue
192
+ raise "Could not find Section object '#{get_name}' (#{get_locator}) after #{timeout} seconds" unless exists?
193
+ end
194
+
195
+ def wait_until_gone(seconds = nil)
196
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
197
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
198
+ wait.until { !exists? }
199
+ rescue
200
+ raise "Section object '#{get_name}' (#{get_locator}) remained visible after #{timeout} seconds" if exists?
201
+ end
202
+
203
+ def wait_until_visible(seconds = nil)
204
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
205
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
206
+ wait.until { visible? }
207
+ rescue
208
+ raise "Could not find Section object '#{get_name}' (#{get_locator}) after #{timeout} seconds" unless visible?
209
+ end
210
+
211
+ def wait_until_hidden(seconds = nil)
212
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
213
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
214
+ wait.until { hidden? }
215
+ rescue
216
+ raise "Section object '#{get_name}' (#{get_locator}) remained visible after #{timeout} seconds" if visible?
217
+ end
218
+
219
+
220
+ def verify_ui_states(ui_states)
221
+ ui_states.each do |ui_object, object_states|
222
+ object_states.each do |property, state|
223
+
224
+
225
+ puts "#{ui_object.get_name} - #{property} = #{state}" if ENV['DEBUG']
226
+
227
+
228
+ case property
229
+ when :exists
230
+ actual = ui_object.exists?
231
+ when :enabled
232
+ actual = ui_object.enabled?
233
+ when :disabled
234
+ actual = ui_object.disabled?
235
+ when :visible
236
+ actual = ui_object.visible?
237
+ when :hidden
238
+ actual = ui_object.hidden?
239
+ when :checked
240
+ actual = ui_object.checked?
241
+ when :selected
242
+ actual = ui_object.selected?
243
+ when :value
244
+ actual = ui_object.get_value
245
+ when :caption
246
+ actual = ui_object.get_caption
247
+ when :name
248
+ actual = ui_object.tag_name
249
+ when :placeholder
250
+ actual = ui_object.get_placeholder
251
+ when :items
252
+ actual = ui_object.get_list_items
253
+ when :itemcount
254
+ actual = ui_object.get_item_count
255
+ end
256
+
257
+ if state.is_a?(Hash) && state.length == 1
258
+ error_msg = "Expected UI object '#{ui_object.get_name}' (#{ui_object.get_locator}) #{property} property to"
259
+ state.each do |key, value|
260
+ case key
261
+ when :lt, :less_than
262
+ ExceptionQueue.enqueue_exception("#{error_msg} be less than #{value} but found '#{actual}'") unless actual < value
263
+ when :lt_eq, :less_than_or_equal
264
+ ExceptionQueue.enqueue_exception("#{error_msg} be less than or equal to #{value} but found '#{actual}'") unless actual <= value
265
+ when :gt, :greater_than
266
+ ExceptionQueue.enqueue_exception("#{error_msg} be greater than #{value} but found '#{actual}'") unless actual > value
267
+ when :gt_eq, :greater_than_or_equal
268
+ ExceptionQueue.enqueue_exception("#{error_msg} be greater than or equal to #{value} but found '#{actual}'") unless actual >= value
269
+ when :starts_with
270
+ ExceptionQueue.enqueue_exception("#{error_msg} start with '#{value}' but found '#{actual}'") unless actual.start_with?(value)
271
+ when :ends_with
272
+ ExceptionQueue.enqueue_exception("#{error_msg} end with '#{value}' but found '#{actual}'") unless actual.end_with?(value)
273
+ when :contains
274
+ ExceptionQueue.enqueue_exception("#{error_msg} contain '#{value}' but found '#{actual}'") unless actual.include?(value)
275
+ when :not_contains, :does_not_contain
276
+ ExceptionQueue.enqueue_exception("#{error_msg} not contain '#{value}' but found '#{actual}'") if actual.include?(value)
277
+ when :not_equal
278
+ ExceptionQueue.enqueue_exception("#{error_msg} not equal '#{value}' but found '#{actual}'") if actual == value
279
+ when :like, :is_like
280
+ actual_like = actual.delete("\n")
281
+ actual_like = actual_like.delete("\r")
282
+ actual_like = actual_like.delete("\t")
283
+ actual_like = actual_like.delete(' ')
284
+ actual_like = actual_like.downcase
285
+ expected = value.delete("\n")
286
+ expected = expected.delete("\r")
287
+ expected = expected.delete("\t")
288
+ expected = expected.delete(' ')
289
+ expected = expected.downcase
290
+ ExceptionQueue.enqueue_exception("#{error_msg} be like '#{value}' but found '#{actual}'") unless actual_like.include?(expected)
291
+ when :translate
292
+ expected = I18n.t(value)
293
+ ExceptionQueue.enqueue_assert_equal(expected, actual, "Expected UI object '#{ui_object.get_name}' (#{ui_object.get_locator}) translated #{property} property")
294
+ end
295
+ end
296
+ else
297
+ ExceptionQueue.enqueue_assert_equal(state, actual, "Expected UI object '#{ui_object.get_name}' (#{ui_object.get_locator}) #{property} property")
298
+ end
299
+ end
300
+ end
301
+ ExceptionQueue.post_exceptions
302
+ end
303
+
304
+ def populate_data_fields(data, wait_time = nil)
305
+ timeout = wait_time.nil? ? 5 : wait_time
306
+ data.each do |data_field, data_param|
307
+ unless data_param.blank?
308
+ # make sure the intended UI target element is visible before trying to set its value
309
+ data_field.wait_until_visible(timeout)
310
+ if data_param == '!DELETE'
311
+ data_field.clear
312
+ else
313
+ case data_field.get_object_type
314
+ when :checkbox
315
+ data_field.set_checkbox_state(data_param.to_bool)
316
+ when :textfield
317
+ data_field.set("#{data_param}\t")
318
+ end
319
+ end
320
+ end
321
+ end
322
+ end
323
+
324
+ private
325
+
326
+ def find_section
327
+ find_element(@strategy, @locator)
328
+ rescue
329
+ nil
330
+ end
331
+ end
332
+ end