testcentricity_mobile 4.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.
@@ -0,0 +1,56 @@
1
+ module TestCentricity
2
+ module AppElements
3
+ class AppCheckBox < AppUIElement
4
+ def initialize(name, parent, locator, context)
5
+ super
6
+ @type = :checkbox
7
+ end
8
+
9
+ # Is checkbox checked?
10
+ #
11
+ # @return [Boolean]
12
+ # @example
13
+ # remember_me_checkbox.checked?
14
+ #
15
+ def checked?
16
+ obj = element
17
+ object_not_found_exception(obj)
18
+ obj.selected?
19
+ end
20
+
21
+ # Set the check state of a checkbox object.
22
+ #
23
+ # @example
24
+ # remember_me_checkbox.check
25
+ #
26
+ def check
27
+ set_checkbox_state(true)
28
+ end
29
+
30
+ # Uncheck a checkbox object.
31
+ #
32
+ # @example
33
+ # remember_me_checkbox.uncheck
34
+ #
35
+ def uncheck
36
+ set_checkbox_state(false)
37
+ end
38
+
39
+ # Set the check state of a checkbox object.
40
+ #
41
+ # @param state [Boolean] true = checked / false = unchecked
42
+ # @example
43
+ # remember_me_checkbox.set_checkbox_state(true)
44
+ #
45
+ def set_checkbox_state(state)
46
+ obj = element
47
+ object_not_found_exception(obj)
48
+ if state
49
+ obj.click unless obj.selected?
50
+ else
51
+ obj.click if obj.selected?
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,10 @@
1
+ module TestCentricity
2
+ module AppElements
3
+ class AppImage < AppUIElement
4
+ def initialize(name, parent, locator, context)
5
+ super
6
+ @type = :image
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module TestCentricity
2
+ module AppElements
3
+ class AppLabel < AppUIElement
4
+ def initialize(name, parent, locator, context)
5
+ super
6
+ @type = :label
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,175 @@
1
+ module TestCentricity
2
+ module AppElements
3
+ class AppList < AppUIElement
4
+ attr_accessor :list_item
5
+ attr_accessor :scrolling
6
+ attr_accessor :item_objects
7
+
8
+ def initialize(name, parent, locator, context)
9
+ super
10
+ @type = :list
11
+ @list_item = nil
12
+ @scrolling = :vertical
13
+ @item_objects = nil
14
+ end
15
+
16
+ def define_list_elements(element_spec)
17
+ element_spec.each do |element, value|
18
+ case element
19
+ when :list_item
20
+ @list_item = value
21
+ when :scrolling
22
+ @scrolling = value
23
+ else
24
+ raise "#{element} is not a recognized list element"
25
+ end
26
+ end
27
+ end
28
+
29
+ def scroll_mode
30
+ obj = element
31
+ object_not_found_exception(obj)
32
+ @scrolling
33
+ end
34
+
35
+ def item_refs
36
+ obj = element
37
+ object_not_found_exception(obj)
38
+ @item_objects
39
+ end
40
+
41
+ # Return the number of items in a list object.
42
+ #
43
+ # @return [Integer]
44
+ # @example
45
+ # num_nav_items = nav_list.get_item_count
46
+ #
47
+ def get_item_count
48
+ obj = element
49
+ object_not_found_exception(obj)
50
+ if Environ.is_ios? && obj.attribute(:type) == 'XCUIElementTypePickerWheel'
51
+ raise 'This method is not supported for XCUIElementTypePickerWheel controls'
52
+ end
53
+ list_loc = get_list_item_locator
54
+ items = obj.find_elements(list_loc.keys[0], list_loc.values[0])
55
+ if items.size > 0 && Environ.is_android?
56
+ start_count = items.count
57
+ direction = @scrolling == :horizontal ? :right : :down
58
+ scroll_count = 0
59
+ loop do
60
+ save_count = items.count
61
+ swipe_gesture(direction)
62
+ scroll_count += 1
63
+ obj.find_elements(list_loc.keys[0], list_loc.values[0]).each do |item|
64
+ items.push(item) unless items.include?(item)
65
+ end
66
+ break if items.count == save_count
67
+ end
68
+ direction = @scrolling == :horizontal ? :left : :up
69
+ scroll_count.times do
70
+ swipe_gesture(direction)
71
+ end
72
+ end
73
+ @item_objects = items if Environ.is_android? && start_count < items.count
74
+ items.count
75
+ end
76
+
77
+ # Return array of strings of all items in a list object.
78
+ #
79
+ # @return [Array]
80
+ # @example
81
+ # nav_items = nav_list.get_options
82
+ #
83
+ def get_list_items
84
+ list_items = []
85
+ obj = element
86
+ object_not_found_exception(obj)
87
+ if Environ.is_ios? && obj.attribute(:type) == 'XCUIElementTypePickerWheel'
88
+ raise 'This method is not supported for XCUIElementTypePickerWheel controls'
89
+ end
90
+ list_loc = get_list_item_locator
91
+ items = obj.find_elements(list_loc.keys[0], list_loc.values[0])
92
+ items.each do |item|
93
+ list_items.push(item.text)
94
+ end
95
+ list_items
96
+ end
97
+
98
+ # Select the specified item in a list object. Accepts a String or Integer.
99
+ #
100
+ # @param item [String, Integer] text or index of item to select
101
+ #
102
+ # @example
103
+ # province_list.choose_item(2)
104
+ # province_list.choose_item('Manitoba')
105
+ #
106
+ def choose_item(item)
107
+ obj = element
108
+ object_not_found_exception(obj)
109
+ if Environ.is_ios? && obj.attribute(:type) == 'XCUIElementTypePickerWheel'
110
+ obj.send_keys(item)
111
+ else
112
+ list_loc = get_list_item_locator
113
+ items = obj.find_elements(list_loc.keys[0], list_loc.values[0])
114
+ if item.is_a?(Integer)
115
+ items[item - 1].click
116
+ else
117
+ items.each do |list_item|
118
+ if list_item.text == item
119
+ list_item.click
120
+ break
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ # Wait until the list's item_count equals the specified value, or until the specified wait time has expired. If the
128
+ # wait time is nil, then the wait time will be Environ.default_max_wait_time.
129
+ #
130
+ # @param value [Integer or Hash] value expected or comparison hash
131
+ # @param seconds [Integer or Float] wait time in seconds
132
+ # @example
133
+ # search_results_list.wait_until_item_count_is(10, 15)
134
+ # or
135
+ # search_results_list.wait_until_item_count_is({ :greater_than_or_equal => 1 }, 5)
136
+ #
137
+ def wait_until_item_count_is(value, seconds = nil)
138
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
139
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
140
+ wait.until { compare(value, get_item_count) }
141
+ rescue
142
+ raise "Value of List #{object_ref_message} failed to equal '#{value}' after #{timeout} seconds" unless get_item_count == value
143
+ end
144
+
145
+ # Wait until the list's item_count changes, or until the specified wait time has expired. If the wait time is nil,
146
+ # then the wait time will be Environ.default_max_wait_time.
147
+ #
148
+ # @param seconds [Integer or Float] wait time in seconds
149
+ # @example
150
+ # search_results_list.wait_until_item_count_changes(10)
151
+ #
152
+ def wait_until_item_count_changes(seconds = nil)
153
+ value = get_item_count
154
+ timeout = seconds.nil? ? Environ.default_max_wait_time : seconds
155
+ wait = Selenium::WebDriver::Wait.new(timeout: timeout)
156
+ wait.until { get_item_count != value }
157
+ rescue
158
+ raise "Value of List #{object_ref_message} failed to change from '#{value}' after #{timeout} seconds" if get_item_count == value
159
+ end
160
+
161
+ private
162
+
163
+ def get_list_item_locator
164
+ if @list_item.nil?
165
+ if Environ.device_os == :ios
166
+ define_list_elements({ :list_item => { class: 'XCUIElementTypeCell' } } )
167
+ else
168
+ define_list_elements({ :list_item => { class: 'android.widget.FrameLayout' } } )
169
+ end
170
+ end
171
+ @list_item
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,66 @@
1
+ module TestCentricity
2
+ module AppElements
3
+ class AppSwitch < AppUIElement
4
+ def initialize(name, parent, locator, context)
5
+ super
6
+ @type = :switch
7
+ end
8
+
9
+ # Is switch in ON state?
10
+ #
11
+ # @return [Boolean]
12
+ # @example
13
+ # use_face_id_switch.on?
14
+ #
15
+ def on?
16
+ obj = element
17
+ object_not_found_exception(obj)
18
+
19
+ if Environ.is_ios?
20
+ state = obj.attribute(:value)
21
+ state.to_bool
22
+ else
23
+ state = obj.attribute(:checked)
24
+ state.boolean? ? state : state == 'true'
25
+ end
26
+ end
27
+
28
+ alias checked? on?
29
+ alias selected? on?
30
+
31
+ # Set the state of a switch object to ON.
32
+ #
33
+ # @example
34
+ # use_face_id_switch.on
35
+ #
36
+ def on
37
+ obj = element
38
+ object_not_found_exception(obj)
39
+ obj.click unless on?
40
+ end
41
+
42
+ # Set the state of a switch object to OFF.
43
+ #
44
+ # @example
45
+ # use_face_id_switch.off
46
+ #
47
+ def off
48
+ obj = element
49
+ object_not_found_exception(obj)
50
+ obj.click if on?
51
+ end
52
+
53
+ # Set the ON/OFF state of a switch object.
54
+ #
55
+ # @param state [Boolean] true = on / false = off
56
+ # @example
57
+ # use_face_id_switch.set_switch_state(true)
58
+ #
59
+ def set_switch_state(state)
60
+ obj = element
61
+ object_not_found_exception(obj)
62
+ state ? on : off
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,51 @@
1
+ module TestCentricity
2
+ module AppElements
3
+ class AppTextField < AppUIElement
4
+ def initialize(name, parent, locator, context)
5
+ super
6
+ @type = :textfield
7
+ end
8
+
9
+ # Is text field set to read-only?
10
+ #
11
+ # @return [Boolean]
12
+ # @example
13
+ # comments_field.read_only?
14
+ #
15
+ def read_only?
16
+ obj = element
17
+ object_not_found_exception(obj)
18
+ !!obj.attribute('readonly')
19
+ end
20
+
21
+ # Return maxlength character count of a text field.
22
+ #
23
+ # @return [Integer]
24
+ # @example
25
+ # max_num_chars = comments_field.get_max_length
26
+ #
27
+ def get_max_length
28
+ obj = element
29
+ object_not_found_exception(obj)
30
+ max_length = obj.attribute('maxlength')
31
+ max_length.to_i unless max_length.blank?
32
+ end
33
+
34
+ # Return placeholder text of a text field.
35
+ #
36
+ # @return [String]
37
+ # @example
38
+ # placeholder_message = username_field.get_placeholder
39
+ #
40
+ def get_placeholder
41
+ obj = element
42
+ object_not_found_exception(obj)
43
+ if AppiumConnect.is_webview?
44
+ obj.attribute('placeholder')
45
+ else
46
+ obj.text
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,71 @@
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
+ attr_accessor :process
10
+
11
+ def initialize(params = {})
12
+ @params = params
13
+ end
14
+
15
+ #
16
+ # Start the Appium Server
17
+ #
18
+ def start
19
+ # terminate any currently running Appium Server
20
+ if running?
21
+ system('killall -9 node')
22
+ puts 'Terminating existing Appium Server'
23
+ sleep(5)
24
+ puts 'Appium Server is being restarted'
25
+ else
26
+ puts 'Appium Server is starting'
27
+ end
28
+ # start new Appium Server
29
+ @process = ChildProcess.build(*parameters)
30
+ process.start
31
+ # wait until confirmation that Appium Server is running
32
+ wait = Selenium::WebDriver::Wait.new(timeout: 30)
33
+ wait.until { running? }
34
+ puts "Appium Server is running - PID = #{process.pid}"
35
+ end
36
+
37
+ #
38
+ # Check to see if Appium Server is running
39
+ #
40
+ def running?
41
+ response = false
42
+ begin
43
+ response = Net::HTTP.get_response(URI('http://0.0.0.0:4723/wd/hub/sessions'))
44
+ rescue
45
+ end
46
+ response && response.code_type == Net::HTTPOK
47
+ end
48
+
49
+ #
50
+ # Stop the Appium Server
51
+ #
52
+ def stop
53
+ process.stop
54
+ puts 'Appium Server has been terminated'
55
+ end
56
+
57
+ private
58
+
59
+ # :nocov:
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
+ # :nocov:
69
+ end
70
+ end
71
+
@@ -0,0 +1,100 @@
1
+ require 'yaml'
2
+ require 'json'
3
+ require 'virtus'
4
+ require 'time'
5
+ require 'chronic'
6
+ require 'faker'
7
+
8
+
9
+ module TestCentricity
10
+
11
+ PRIMARY_DATA_PATH ||= 'config/test_data/'
12
+ PRIMARY_DATA_FILE ||= "#{PRIMARY_DATA_PATH}data."
13
+ YML_PRIMARY_DATA_FILE ||= "#{PRIMARY_DATA_FILE}yml"
14
+ JSON_PRIMARY_DATA_FILE ||= "#{PRIMARY_DATA_FILE}json"
15
+
16
+
17
+ class DataObject
18
+ attr_accessor :current
19
+ attr_accessor :context
20
+ attr_accessor :hash_table
21
+
22
+ def initialize(data)
23
+ @hash_table = data
24
+ end
25
+
26
+ def self.current
27
+ @current
28
+ end
29
+
30
+ def self.current=(current)
31
+ @current = current
32
+ end
33
+ end
34
+
35
+
36
+ class DataPresenter
37
+ include Virtus.model
38
+
39
+ attr_accessor :current
40
+ attr_accessor :context
41
+
42
+ def initialize(data)
43
+ self.attributes = data unless data.nil?
44
+ end
45
+
46
+ def self.current
47
+ @current
48
+ end
49
+
50
+ def self.current=(current)
51
+ @current = current
52
+ end
53
+ end
54
+
55
+
56
+ # :nocov:
57
+ class DataSource
58
+ attr_accessor :file_path
59
+ attr_accessor :node
60
+
61
+ def read_yaml_node_data(file_name, node_name)
62
+ @file_path = "#{PRIMARY_DATA_PATH}#{file_name}"
63
+ @node = node_name
64
+ data = YAML.load_file(@file_path)
65
+ data[node_name]
66
+ end
67
+
68
+ def read_json_node_data(file_name, node_name)
69
+ @file_path = "#{PRIMARY_DATA_PATH}#{file_name}"
70
+ @node = node_name
71
+ raw_data = File.read(@file_path)
72
+ data = JSON.parse(raw_data)
73
+ data[node_name]
74
+ end
75
+
76
+ private
77
+
78
+ def self.calculate_dynamic_value(value)
79
+ test_value = value.split('!', 2)
80
+ parameter = test_value[1].split('.', 2)
81
+ case parameter[0]
82
+ when 'Date'
83
+ result = eval("Chronic.parse('#{parameter[1]}')")
84
+ when 'FormattedDate', 'FormatDate'
85
+ date_time_params = parameter[1].split(' format! ', 2)
86
+ date_time = eval("Chronic.parse('#{date_time_params[0].strip}')")
87
+ result = date_time.to_s.format_date_time("#{date_time_params[1].strip}")
88
+ else
89
+ result = if Faker.constants.include?(parameter[0].to_sym)
90
+ eval("Faker::#{parameter[0]}.#{parameter[1]}")
91
+ else
92
+ eval(test_value[1])
93
+ end
94
+ end
95
+ result.to_s
96
+ end
97
+ end
98
+ # :nocov:
99
+ end
100
+