testcentricity_mobile 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.yardopts +3 -0
- data/CHANGELOG.md +105 -0
- data/LICENSE.md +27 -0
- data/README.md +1795 -0
- data/lib/testcentricity_mobile/app_core/appium_connect_helper.rb +634 -0
- data/lib/testcentricity_mobile/app_core/screen_object.rb +413 -0
- data/lib/testcentricity_mobile/app_core/screen_objects_helper.rb +183 -0
- data/lib/testcentricity_mobile/app_core/screen_section.rb +607 -0
- data/lib/testcentricity_mobile/app_elements/alert.rb +152 -0
- data/lib/testcentricity_mobile/app_elements/app_element.rb +692 -0
- data/lib/testcentricity_mobile/app_elements/button.rb +10 -0
- data/lib/testcentricity_mobile/app_elements/checkbox.rb +56 -0
- data/lib/testcentricity_mobile/app_elements/image.rb +10 -0
- data/lib/testcentricity_mobile/app_elements/label.rb +10 -0
- data/lib/testcentricity_mobile/app_elements/list.rb +175 -0
- data/lib/testcentricity_mobile/app_elements/switch.rb +66 -0
- data/lib/testcentricity_mobile/app_elements/textfield.rb +51 -0
- data/lib/testcentricity_mobile/appium_server.rb +71 -0
- data/lib/testcentricity_mobile/data_objects/data_objects_helper.rb +100 -0
- data/lib/testcentricity_mobile/data_objects/environment.rb +416 -0
- data/lib/testcentricity_mobile/exception_queue_helper.rb +160 -0
- data/lib/testcentricity_mobile/utility_helpers.rb +48 -0
- data/lib/testcentricity_mobile/version.rb +3 -0
- data/lib/testcentricity_mobile/world_extensions.rb +61 -0
- data/lib/testcentricity_mobile.rb +99 -0
- metadata +317 -0
@@ -0,0 +1,416 @@
|
|
1
|
+
module TestCentricity
|
2
|
+
class EnvironData < TestCentricity::DataSource
|
3
|
+
attr_accessor :current
|
4
|
+
attr_accessor :data_source_type
|
5
|
+
attr_accessor :generic_data
|
6
|
+
attr_accessor :environ_specific_data
|
7
|
+
|
8
|
+
def self.find_environ(environ_name, source_type = :yaml)
|
9
|
+
raise 'No environment specified' if environ_name.nil?
|
10
|
+
|
11
|
+
@data_source_type = source_type
|
12
|
+
data = case source_type
|
13
|
+
when :yaml
|
14
|
+
# read generic test data from data.yml file
|
15
|
+
@generic_data ||= YAML.load_file(YML_PRIMARY_DATA_FILE)
|
16
|
+
# read environment specific test data
|
17
|
+
data_file = "#{PRIMARY_DATA_PATH}#{environ_name}_data.yml"
|
18
|
+
@environ_specific_data = if File.exist?(data_file)
|
19
|
+
YAML.load_file(data_file)
|
20
|
+
else
|
21
|
+
{}
|
22
|
+
end
|
23
|
+
read('Environments', environ_name)
|
24
|
+
when :json
|
25
|
+
# read generic test data from data.json file
|
26
|
+
raw_data = File.read(JSON_PRIMARY_DATA_FILE)
|
27
|
+
@generic_data = JSON.parse(raw_data)
|
28
|
+
# read environment specific test data
|
29
|
+
data_file = "#{PRIMARY_DATA_PATH}#{environ_name}_data.json"
|
30
|
+
@environ_specific_data = if File.exist?(data_file)
|
31
|
+
raw_data = File.read(data_file)
|
32
|
+
JSON.parse(raw_data)
|
33
|
+
else
|
34
|
+
{}
|
35
|
+
end
|
36
|
+
|
37
|
+
read('Environments', environ_name)
|
38
|
+
else
|
39
|
+
raise "#{source_type} is not a supported data source type"
|
40
|
+
end
|
41
|
+
@current = Environ.new(data)
|
42
|
+
Environ.current = @current
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.read(key_name, node_name)
|
46
|
+
if @environ_specific_data.key?(key_name) && @environ_specific_data[key_name].key?(node_name)
|
47
|
+
node_data = @environ_specific_data[key_name][node_name]
|
48
|
+
else
|
49
|
+
raise "No key named #{key_name} in generic and environment-specific data" unless @generic_data.key?(key_name)
|
50
|
+
raise "No node named #{node_name} in #{key_name} section of generic and environment-specific data" unless @generic_data[key_name].key?(node_name)
|
51
|
+
|
52
|
+
node_data = @generic_data[key_name][node_name]
|
53
|
+
end
|
54
|
+
|
55
|
+
if node_data.is_a?(Hash)
|
56
|
+
node_data.each do |key, value|
|
57
|
+
node_data[key] = calculate_dynamic_value(value) if value.to_s.start_with?('eval!')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
node_data
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
class Environ < TestCentricity::DataObject
|
66
|
+
@session_id = Time.now.strftime('%d%H%M%S%L')
|
67
|
+
@session_time_stamp = Time.now.strftime('%Y%m%d%H%M%S')
|
68
|
+
@test_environment = ENV['TEST_ENVIRONMENT']
|
69
|
+
@a11y_standard = ENV['ACCESSIBILITY_STANDARD'] || 'best-practice'
|
70
|
+
@locale = ENV['LOCALE'] || 'en'
|
71
|
+
@language = ENV['LANGUAGE'] || 'English'
|
72
|
+
@screen_shots = []
|
73
|
+
|
74
|
+
attr_accessor :test_environment
|
75
|
+
attr_accessor :session_state
|
76
|
+
attr_accessor :session_code
|
77
|
+
attr_accessor :app_session_id
|
78
|
+
attr_accessor :os
|
79
|
+
attr_accessor :device
|
80
|
+
attr_accessor :device_name
|
81
|
+
attr_accessor :device_type
|
82
|
+
attr_accessor :device_os
|
83
|
+
attr_accessor :device_os_version
|
84
|
+
attr_accessor :device_orientation
|
85
|
+
attr_accessor :screen_size
|
86
|
+
attr_accessor :platform
|
87
|
+
attr_accessor :driver
|
88
|
+
attr_accessor :driver_name
|
89
|
+
attr_accessor :appium_driver
|
90
|
+
attr_accessor :tunneling
|
91
|
+
attr_accessor :locale
|
92
|
+
attr_accessor :language
|
93
|
+
|
94
|
+
attr_accessor :parallel
|
95
|
+
attr_accessor :process_num
|
96
|
+
|
97
|
+
attr_accessor :signed_in
|
98
|
+
attr_accessor :portal_status
|
99
|
+
attr_accessor :portal_context
|
100
|
+
|
101
|
+
attr_accessor :user_id
|
102
|
+
attr_accessor :password
|
103
|
+
attr_accessor :app_id
|
104
|
+
attr_accessor :api_key
|
105
|
+
attr_accessor :option1
|
106
|
+
attr_accessor :option2
|
107
|
+
attr_accessor :option3
|
108
|
+
attr_accessor :option4
|
109
|
+
attr_accessor :dns
|
110
|
+
attr_accessor :db_username
|
111
|
+
attr_accessor :db_password
|
112
|
+
|
113
|
+
attr_accessor :ios_app_path
|
114
|
+
attr_accessor :ios_ipa_path
|
115
|
+
attr_accessor :ios_bundle_id
|
116
|
+
attr_accessor :ios_test_id
|
117
|
+
attr_accessor :android_apk_path
|
118
|
+
attr_accessor :android_app_id
|
119
|
+
attr_accessor :android_test_id
|
120
|
+
attr_accessor :default_max_wait_time
|
121
|
+
attr_accessor :deep_link_prefix
|
122
|
+
|
123
|
+
def initialize(data)
|
124
|
+
@user_id = data['USER_ID']
|
125
|
+
@password = data['PASSWORD']
|
126
|
+
@app_id = data['APP_ID']
|
127
|
+
@api_key = data['API_KEY']
|
128
|
+
@option1 = data['OPTIONAL_1']
|
129
|
+
@option2 = data['OPTIONAL_2']
|
130
|
+
@option3 = data['OPTIONAL_3']
|
131
|
+
@option4 = data['OPTIONAL_4']
|
132
|
+
@dns = data['DNS']
|
133
|
+
@db_username = data['DB_USERNAME']
|
134
|
+
@db_password = data['DB_PASSWORD']
|
135
|
+
@ios_app_path = data['IOS_APP_PATH']
|
136
|
+
@ios_ipa_path = data['IOS_IPA_PATH']
|
137
|
+
@ios_bundle_id = data['IOS_BUNDLE_ID']
|
138
|
+
@ios_test_id = data['IOS_TEST_ID']
|
139
|
+
@android_apk_path = data['ANDROID_APK_PATH']
|
140
|
+
@android_app_id = data['ANDROID_APP_ID']
|
141
|
+
@android_test_id = data['ANDROID_TEST_ID']
|
142
|
+
@deep_link_prefix = data['DEEP_LINK_PREFIX']
|
143
|
+
|
144
|
+
super
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.new_app_session
|
148
|
+
@app_session_id = Time.now.strftime('%Y%m%d%H%M%S%L')
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.app_session_id
|
152
|
+
@app_session_id
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.session_code
|
156
|
+
if @session_code.nil?
|
157
|
+
characters = ('a'..'z').to_a
|
158
|
+
@session_code = (0..12).map { characters.sample }.join
|
159
|
+
end
|
160
|
+
@session_code
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.session_id
|
164
|
+
@session_id
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.session_time_stamp
|
168
|
+
@session_time_stamp
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.parallel=(state)
|
172
|
+
@parallel = state
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.parallel
|
176
|
+
@parallel
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.process_num=(num)
|
180
|
+
@process_num = num
|
181
|
+
end
|
182
|
+
|
183
|
+
def self.process_num
|
184
|
+
@process_num
|
185
|
+
end
|
186
|
+
|
187
|
+
def self.test_environment
|
188
|
+
if @test_environment.blank?
|
189
|
+
nil
|
190
|
+
else
|
191
|
+
@test_environment.downcase.to_sym
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def self.default_max_wait_time=(timeout)
|
196
|
+
@default_max_wait_time = timeout
|
197
|
+
end
|
198
|
+
|
199
|
+
def self.default_max_wait_time
|
200
|
+
@default_max_wait_time
|
201
|
+
end
|
202
|
+
|
203
|
+
def self.session_state=(session_state)
|
204
|
+
@session_state = session_state
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.session_state
|
208
|
+
@session_state
|
209
|
+
end
|
210
|
+
|
211
|
+
def self.os=(os)
|
212
|
+
@os = os
|
213
|
+
end
|
214
|
+
|
215
|
+
def self.os
|
216
|
+
@os
|
217
|
+
end
|
218
|
+
|
219
|
+
def self.device=(device)
|
220
|
+
@device = device
|
221
|
+
end
|
222
|
+
|
223
|
+
def self.device
|
224
|
+
@device
|
225
|
+
end
|
226
|
+
|
227
|
+
def self.is_device?
|
228
|
+
@device == :device
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.is_simulator?
|
232
|
+
@device == :simulator
|
233
|
+
end
|
234
|
+
|
235
|
+
def self.is_web?
|
236
|
+
@device == :web
|
237
|
+
end
|
238
|
+
|
239
|
+
def self.device_type=(type)
|
240
|
+
type = type.downcase.to_sym if type.is_a?(String)
|
241
|
+
@device_type = type
|
242
|
+
end
|
243
|
+
|
244
|
+
def self.device_type
|
245
|
+
@device_type
|
246
|
+
end
|
247
|
+
|
248
|
+
def self.device_name=(name)
|
249
|
+
@device_name = name
|
250
|
+
end
|
251
|
+
|
252
|
+
def self.device_name
|
253
|
+
@device_name
|
254
|
+
end
|
255
|
+
|
256
|
+
def self.device_os=(os)
|
257
|
+
@device_os = os.downcase.to_sym
|
258
|
+
end
|
259
|
+
|
260
|
+
def self.device_os
|
261
|
+
@device_os
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.device_os_version=(version)
|
265
|
+
@device_os_version = version
|
266
|
+
end
|
267
|
+
|
268
|
+
def self.device_os_version
|
269
|
+
@device_os_version
|
270
|
+
end
|
271
|
+
|
272
|
+
def self.is_ios?
|
273
|
+
@device_os == :ios
|
274
|
+
end
|
275
|
+
|
276
|
+
def self.is_android?
|
277
|
+
@device_os == :android
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.device_orientation=(orientation)
|
281
|
+
orientation = orientation.downcase.to_sym if orientation.is_a?(String)
|
282
|
+
@device_orientation = orientation
|
283
|
+
end
|
284
|
+
|
285
|
+
def self.device_orientation
|
286
|
+
@device_orientation
|
287
|
+
end
|
288
|
+
|
289
|
+
def self.screen_size=(size)
|
290
|
+
@screen_size = size
|
291
|
+
end
|
292
|
+
|
293
|
+
def self.screen_size
|
294
|
+
@screen_size
|
295
|
+
end
|
296
|
+
|
297
|
+
def self.driver=(type)
|
298
|
+
@driver = type
|
299
|
+
end
|
300
|
+
|
301
|
+
def self.driver
|
302
|
+
@driver
|
303
|
+
end
|
304
|
+
|
305
|
+
def self.driver_name=(name)
|
306
|
+
name = name.downcase.to_sym if name.is_a?(String)
|
307
|
+
@driver_name = name
|
308
|
+
end
|
309
|
+
|
310
|
+
def self.driver_name
|
311
|
+
@driver_name
|
312
|
+
end
|
313
|
+
|
314
|
+
def self.appium_driver=(driver_instance)
|
315
|
+
@appium_driver = driver_instance
|
316
|
+
end
|
317
|
+
|
318
|
+
def self.appium_driver
|
319
|
+
@appium_driver
|
320
|
+
end
|
321
|
+
|
322
|
+
def self.tunneling=(state)
|
323
|
+
@tunneling = state
|
324
|
+
end
|
325
|
+
|
326
|
+
def self.tunneling
|
327
|
+
@tunneling
|
328
|
+
end
|
329
|
+
|
330
|
+
def self.language=(language)
|
331
|
+
@language = language
|
332
|
+
end
|
333
|
+
|
334
|
+
def self.language
|
335
|
+
@language
|
336
|
+
end
|
337
|
+
|
338
|
+
def self.locale=(locale)
|
339
|
+
@locale = locale
|
340
|
+
end
|
341
|
+
|
342
|
+
def self.locale
|
343
|
+
@locale
|
344
|
+
end
|
345
|
+
|
346
|
+
def self.platform=(platform)
|
347
|
+
@platform = platform
|
348
|
+
end
|
349
|
+
|
350
|
+
def self.platform
|
351
|
+
@platform
|
352
|
+
end
|
353
|
+
|
354
|
+
def self.is_mobile?
|
355
|
+
@platform == :mobile
|
356
|
+
end
|
357
|
+
|
358
|
+
def self.set_signed_in(signed_in)
|
359
|
+
@signed_in = signed_in
|
360
|
+
end
|
361
|
+
|
362
|
+
def self.is_signed_in?
|
363
|
+
@signed_in
|
364
|
+
end
|
365
|
+
|
366
|
+
def self.portal_state=(portal_state)
|
367
|
+
@portal_status = portal_state
|
368
|
+
end
|
369
|
+
|
370
|
+
def self.portal_state
|
371
|
+
@portal_status
|
372
|
+
end
|
373
|
+
|
374
|
+
def self.portal_context=(portal_context)
|
375
|
+
@portal_context = portal_context
|
376
|
+
end
|
377
|
+
|
378
|
+
def self.portal_context
|
379
|
+
@portal_context
|
380
|
+
end
|
381
|
+
|
382
|
+
def self.set_external_page(state)
|
383
|
+
@external_page = state
|
384
|
+
end
|
385
|
+
|
386
|
+
def self.save_screen_shot(screen_shot)
|
387
|
+
@screen_shots.push(screen_shot)
|
388
|
+
end
|
389
|
+
|
390
|
+
def self.get_screen_shots
|
391
|
+
@screen_shots
|
392
|
+
end
|
393
|
+
|
394
|
+
def self.reset_contexts
|
395
|
+
@screen_shots = []
|
396
|
+
end
|
397
|
+
|
398
|
+
# :nocov:
|
399
|
+
def self.report_header
|
400
|
+
# build the Cucumber HTML report header
|
401
|
+
report_header = "\n<b><u>TEST ENVIRONMENT</u>:</b> #{ENV['TEST_ENVIRONMENT']}\n"
|
402
|
+
report_header = "#{report_header} <b>Driver:</b>\t #{Environ.driver}\n" if Environ.driver
|
403
|
+
report_header = "#{report_header} <b>Driver Name:</b>\t #{Environ.driver_name}\n" if Environ.driver_name
|
404
|
+
report_header = "#{report_header} <b>Platform:</b>\t #{Environ.platform}\n" if Environ.platform
|
405
|
+
report_header = "#{report_header} <b>Device:</b>\t #{Environ.device_name}\n" if Environ.device_name
|
406
|
+
report_header = "#{report_header} <b>Device OS:</b>\t #{Environ.device_os} #{Environ.device_os_version}\n" if Environ.device_os
|
407
|
+
report_header = "#{report_header} <b>Device type:</b>\t #{Environ.device_type}\n" if Environ.device_type
|
408
|
+
report_header = "#{report_header} <b>OS:</b>\t\t #{Environ.os}\n" if Environ.os
|
409
|
+
report_header = "#{report_header} <b>Locale:</b>\t #{Environ.locale}\n" if Environ.locale
|
410
|
+
report_header = "#{report_header} <b>Language:</b>\t #{Environ.language}\n" if Environ.language
|
411
|
+
report_header = "#{report_header} <b>Country:</b>\t #{ENV['COUNTRY']}\n" if ENV['COUNTRY']
|
412
|
+
"#{report_header}\n\n"
|
413
|
+
end
|
414
|
+
# :nocov:
|
415
|
+
end
|
416
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module TestCentricity
|
2
|
+
class ExceptionQueue
|
3
|
+
attr_accessor :error_queue
|
4
|
+
attr_accessor :active_ui_element
|
5
|
+
|
6
|
+
def self.enqueue_assert_equal(expected, actual, error_message)
|
7
|
+
is_equal = if expected.is_a?(String) && actual.is_a?(String)
|
8
|
+
expected.downcase.strip == actual.downcase.strip
|
9
|
+
else
|
10
|
+
expected == actual
|
11
|
+
end
|
12
|
+
unless is_equal
|
13
|
+
enqueue("#{error_message} to be\n '#{expected}'\nbut found\n '#{actual}'")
|
14
|
+
enqueue_screenshot
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.enqueue_assert_not_equal(expected, actual, error_message)
|
19
|
+
unless expected != actual
|
20
|
+
enqueue("#{error_message} to not be equal to '#{expected}'")
|
21
|
+
enqueue_screenshot
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.enqueue_exception(error_message)
|
26
|
+
enqueue(error_message)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.post_exceptions(preample_message = nil)
|
30
|
+
unless @error_queue.nil?
|
31
|
+
unless preample_message.nil?
|
32
|
+
@error_queue = "#{preample_message} - The following errors were found:\n_____________________________\n#{@error_queue}"
|
33
|
+
end
|
34
|
+
raise @error_queue
|
35
|
+
end
|
36
|
+
ensure
|
37
|
+
@error_queue = nil
|
38
|
+
@active_ui_element = nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.enqueue_comparison(ui_object, state, actual, error_msg)
|
42
|
+
@active_ui_element = ui_object
|
43
|
+
if state.is_a?(Hash) && state.length == 1
|
44
|
+
state.each do |key, value|
|
45
|
+
case key
|
46
|
+
when :lt, :less_than
|
47
|
+
enqueue_exception("#{error_msg} be less than #{value} but found '#{actual}'") unless actual < value
|
48
|
+
when :lt_eq, :less_than_or_equal
|
49
|
+
enqueue_exception("#{error_msg} be less than or equal to #{value} but found '#{actual}'") unless actual <= value
|
50
|
+
when :gt, :greater_than
|
51
|
+
enqueue_exception("#{error_msg} be greater than #{value} but found '#{actual}'") unless actual > value
|
52
|
+
when :gt_eq, :greater_than_or_equal
|
53
|
+
enqueue_exception("#{error_msg} be greater than or equal to #{value} but found '#{actual}'") unless actual >= value
|
54
|
+
when :starts_with
|
55
|
+
enqueue_exception("#{error_msg} start with '#{value}' but found '#{actual}'") unless actual.start_with?(value)
|
56
|
+
when :ends_with
|
57
|
+
enqueue_exception("#{error_msg} end with '#{value}' but found '#{actual}'") unless actual.end_with?(value)
|
58
|
+
when :contains
|
59
|
+
enqueue_exception("#{error_msg} contain '#{value}' but found '#{actual}'") unless actual.include?(value)
|
60
|
+
when :not_contains, :does_not_contain
|
61
|
+
enqueue_exception("#{error_msg} not contain '#{value}' but found '#{actual}'") if actual.include?(value)
|
62
|
+
when :not_equal
|
63
|
+
enqueue_exception("#{error_msg} not equal '#{value}' but found '#{actual}'") if actual == value
|
64
|
+
when :like, :is_like
|
65
|
+
actual_like = actual.delete("\n")
|
66
|
+
actual_like = actual_like.delete("\r")
|
67
|
+
actual_like = actual_like.delete("\t")
|
68
|
+
actual_like = actual_like.delete(' ')
|
69
|
+
actual_like = actual_like.downcase
|
70
|
+
expected = value.delete("\n")
|
71
|
+
expected = expected.delete("\r")
|
72
|
+
expected = expected.delete("\t")
|
73
|
+
expected = expected.delete(' ')
|
74
|
+
expected = expected.downcase
|
75
|
+
enqueue_exception("#{error_msg} be like '#{value}' but found '#{actual}'") unless actual_like.include?(expected)
|
76
|
+
when :translate
|
77
|
+
expected = translate(value)
|
78
|
+
enqueue_assert_equal(expected, actual, error_msg)
|
79
|
+
when :translate_upcase
|
80
|
+
expected = translate(value)
|
81
|
+
expected = expected.is_a?(Array) ? expected.map(&:upcase) : expected.upcase
|
82
|
+
enqueue_assert_equal(expected, actual, error_msg)
|
83
|
+
when :translate_downcase
|
84
|
+
expected = translate(value)
|
85
|
+
expected = expected.is_a?(Array) ? expected.map(&:downcase) : expected.downcase
|
86
|
+
enqueue_assert_equal(expected, actual, error_msg)
|
87
|
+
when :translate_capitalize
|
88
|
+
expected = translate(value)
|
89
|
+
expected = expected.is_a?(Array) ? expected.map(&:capitalize) : expected.capitalize
|
90
|
+
enqueue_assert_equal(expected, actual, error_msg)
|
91
|
+
when :translate_titlecase
|
92
|
+
expected = translate(value)
|
93
|
+
expected = if expected.is_a?(Array)
|
94
|
+
result = []
|
95
|
+
expected.each do |item|
|
96
|
+
result.push("#{item.split.each{ |item| item.capitalize! }.join(' ')}")
|
97
|
+
end
|
98
|
+
result
|
99
|
+
else
|
100
|
+
"#{expected.split.each{ |expected| expected.capitalize! }.join(' ')}"
|
101
|
+
end
|
102
|
+
enqueue_assert_equal(expected, actual, error_msg)
|
103
|
+
else
|
104
|
+
raise "#{key} is not a valid comparison key"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
else
|
108
|
+
enqueue_assert_equal(state, actual, error_msg)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def self.enqueue(message)
|
115
|
+
@error_queue = "#{@error_queue}#{message}\n\n"
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.enqueue_screenshot
|
119
|
+
timestamp = Time.now.strftime('%Y%m%d%H%M%S%L')
|
120
|
+
filename = "Screenshot-#{timestamp}.png"
|
121
|
+
path = File.join Dir.pwd, 'reports/screenshots/', filename
|
122
|
+
# take screenshot
|
123
|
+
AppiumConnect.take_screenshot(path)
|
124
|
+
# add screenshot to queue
|
125
|
+
puts "Screenshot saved at #{path}"
|
126
|
+
screen_shot = {path: path, filename: filename}
|
127
|
+
Environ.save_screen_shot(screen_shot)
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.translate(*args, **opts)
|
131
|
+
opts[:locale] ||= I18n.locale
|
132
|
+
opts[:raise] = true
|
133
|
+
I18n.translate(*args, **opts)
|
134
|
+
rescue I18n::MissingTranslationData => err
|
135
|
+
puts err
|
136
|
+
opts[:locale] = :en
|
137
|
+
|
138
|
+
# fallback to en if the translation is missing. If the translation isn't
|
139
|
+
# in en, then raise again.
|
140
|
+
disable_enforce_available_locales do
|
141
|
+
I18n.translate(*args, **opts)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.disable_enforce_available_locales
|
146
|
+
saved_enforce_available_locales = I18n.enforce_available_locales
|
147
|
+
I18n.enforce_available_locales = false
|
148
|
+
yield
|
149
|
+
ensure
|
150
|
+
I18n.enforce_available_locales = saved_enforce_available_locales
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
class ObjectNotFoundError < StandardError
|
156
|
+
def initialize(message)
|
157
|
+
super(message)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class Object
|
2
|
+
def blank?
|
3
|
+
respond_to?(:empty?) ? empty? : !self
|
4
|
+
end
|
5
|
+
|
6
|
+
def present?
|
7
|
+
!blank?
|
8
|
+
end
|
9
|
+
|
10
|
+
def boolean?
|
11
|
+
[true, false].include? self
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
class String
|
17
|
+
def to_bool
|
18
|
+
return true if self == true || self =~ (/(true|t|yes|y|x|1)$/i)
|
19
|
+
return false if self == false || self.blank? || self =~ (/(false|f|no|n|0)$/i)
|
20
|
+
raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
|
21
|
+
end
|
22
|
+
|
23
|
+
def string_between(marker1, marker2)
|
24
|
+
self[/#{Regexp.escape(marker1)}(.*?)#{Regexp.escape(marker2)}/m, 1]
|
25
|
+
end
|
26
|
+
|
27
|
+
def format_date_time(date_time_format)
|
28
|
+
return if self.blank?
|
29
|
+
new_date = DateTime.parse(self)
|
30
|
+
if ENV['LOCALE'] && date_time_format.is_a?(Symbol)
|
31
|
+
I18n.l(new_date, format: date_time_format)
|
32
|
+
else
|
33
|
+
new_date.strftime(date_time_format)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def titlecase
|
38
|
+
"#{self.split.each{ |text| text.capitalize! }.join(' ')}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def is_int?
|
42
|
+
Integer(self) && true rescue false
|
43
|
+
end
|
44
|
+
|
45
|
+
def is_float?
|
46
|
+
Float(self) && true rescue false
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module WorldData
|
2
|
+
def environs
|
3
|
+
@environs ||= TestCentricity::EnvironData
|
4
|
+
end
|
5
|
+
|
6
|
+
# instantiate and register all data objects specified in data_objects method
|
7
|
+
#
|
8
|
+
def instantiate_data_objects
|
9
|
+
# return if data objects have already been instantiated and registered
|
10
|
+
return if TestCentricity::DataManager.loaded?
|
11
|
+
|
12
|
+
# instantiate all data objects
|
13
|
+
@data = {}
|
14
|
+
data_objects.each do |data_type, data_class|
|
15
|
+
@data[data_type] = data_class.new unless @data.has_key?(data_type)
|
16
|
+
# define data object accessor method
|
17
|
+
define_method(data_type) do
|
18
|
+
if instance_variable_defined?(:"@#{data_type}")
|
19
|
+
instance_variable_get(:"@#{data_type}")
|
20
|
+
else
|
21
|
+
instance_variable_set(:"@#{data_type}", TestCentricity::DataManager.find_data_object(data_type))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
# register all data objects with DataManager
|
26
|
+
TestCentricity::DataManager.register_data_objects(@data)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
module WorldScreens
|
32
|
+
# instantiate and register all screen objects specified in screen_objects method
|
33
|
+
#
|
34
|
+
def instantiate_screen_objects
|
35
|
+
# return if screen objects have already been instantiated and registered
|
36
|
+
return if TestCentricity::ScreenManager.loaded?
|
37
|
+
|
38
|
+
# instantiate all screen objects
|
39
|
+
@screens = {}
|
40
|
+
screen_objects.each do |screen_object, screen_class|
|
41
|
+
obj = screen_class.new
|
42
|
+
@screens[screen_object] = obj unless @screens.has_key?(screen_object)
|
43
|
+
screen_names = obj.screen_name
|
44
|
+
screen_names = Array(screen_names) if screen_names.is_a? String
|
45
|
+
screen_names.each do |name|
|
46
|
+
screen_key = name.gsub(/\s+/, '').downcase.to_sym
|
47
|
+
@screens[screen_key] = obj unless @screens.has_key?(screen_key)
|
48
|
+
end
|
49
|
+
# define screen object accessor method
|
50
|
+
define_method(screen_object) do
|
51
|
+
if instance_variable_defined?(:"@#{screen_object}")
|
52
|
+
instance_variable_get(:"@#{screen_object}")
|
53
|
+
else
|
54
|
+
instance_variable_set(:"@#{screen_object}", TestCentricity::ScreenManager.find_screen(screen_object))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
# register all screen objects with ScreenManager
|
59
|
+
TestCentricity::ScreenManager.register_screen_objects(@screens)
|
60
|
+
end
|
61
|
+
end
|