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.
- 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
|