testcentricity_mobile 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+