testcentricity_apps 4.0.10

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 (31) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +3 -0
  3. data/CHANGELOG.md +193 -0
  4. data/LICENSE.md +27 -0
  5. data/README.md +2297 -0
  6. data/lib/testcentricity_apps/app_core/appium_connect_helper.rb +667 -0
  7. data/lib/testcentricity_apps/app_core/screen_object.rb +494 -0
  8. data/lib/testcentricity_apps/app_core/screen_objects_helper.rb +211 -0
  9. data/lib/testcentricity_apps/app_core/screen_section.rb +669 -0
  10. data/lib/testcentricity_apps/app_elements/alert.rb +152 -0
  11. data/lib/testcentricity_apps/app_elements/app_element.rb +728 -0
  12. data/lib/testcentricity_apps/app_elements/button.rb +10 -0
  13. data/lib/testcentricity_apps/app_elements/checkbox.rb +61 -0
  14. data/lib/testcentricity_apps/app_elements/image.rb +10 -0
  15. data/lib/testcentricity_apps/app_elements/label.rb +10 -0
  16. data/lib/testcentricity_apps/app_elements/list.rb +188 -0
  17. data/lib/testcentricity_apps/app_elements/menu.rb +159 -0
  18. data/lib/testcentricity_apps/app_elements/menubar.rb +78 -0
  19. data/lib/testcentricity_apps/app_elements/radio.rb +61 -0
  20. data/lib/testcentricity_apps/app_elements/selectlist.rb +126 -0
  21. data/lib/testcentricity_apps/app_elements/switch.rb +66 -0
  22. data/lib/testcentricity_apps/app_elements/textfield.rb +51 -0
  23. data/lib/testcentricity_apps/appium_server.rb +76 -0
  24. data/lib/testcentricity_apps/data_objects/data_objects_helper.rb +100 -0
  25. data/lib/testcentricity_apps/data_objects/environment.rb +423 -0
  26. data/lib/testcentricity_apps/exception_queue_helper.rb +160 -0
  27. data/lib/testcentricity_apps/utility_helpers.rb +48 -0
  28. data/lib/testcentricity_apps/version.rb +3 -0
  29. data/lib/testcentricity_apps/world_extensions.rb +61 -0
  30. data/lib/testcentricity_apps.rb +103 -0
  31. metadata +322 -0
@@ -0,0 +1,667 @@
1
+ require 'appium_lib'
2
+ require 'json'
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'uri'
6
+
7
+
8
+ module TestCentricity
9
+ module AppiumConnect
10
+ attr_accessor :driver
11
+ attr_accessor :running
12
+ attr_accessor :endpoint
13
+ attr_accessor :capabilities
14
+ attr_accessor :global_scope
15
+
16
+ # Create a new driver instance with capabilities specified in the options parameter, or via Environment Variables.
17
+ # Refer to the `Connecting to a Mobile Simulator or Device` section of the ruby docs for this gem.
18
+ #
19
+ def self.initialize_appium(options = nil)
20
+ @endpoint = nil
21
+ @capabilities = nil
22
+ @running = false
23
+ @global_scope = false
24
+ Environ.driver_name = nil
25
+ Environ.device_orientation = nil
26
+ Environ.platform = :mobile
27
+ Environ.device = :simulator
28
+
29
+ if options.is_a?(Hash)
30
+ @endpoint = options[:endpoint] if options.key?(:endpoint)
31
+ @capabilities = options[:capabilities] if options.key?(:capabilities)
32
+ @global_scope = options[:global_driver] if options.key?(:global_driver)
33
+ Environ.driver = options[:driver] if options.key?(:driver)
34
+ Environ.driver_name = options[:driver_name] if options.key?(:driver_name)
35
+ Environ.device_type = options[:device_type] if options.key?(:device_type)
36
+ end
37
+ if @capabilities.nil?
38
+ Environ.driver = ENV['DRIVER'].downcase.to_sym if ENV['DRIVER']
39
+ Environ.device_type = ENV['DEVICE_TYPE'] if ENV['DEVICE_TYPE']
40
+ Environ.device_orientation = ENV['ORIENTATION'] if ENV['ORIENTATION']
41
+ else
42
+ raise ':browserName is specified in capabilities' if @capabilities[:browserName]
43
+ end
44
+
45
+ raise 'You must specify a driver' if Environ.driver.nil?
46
+ raise 'You must specify a device type - :phone or :tablet' if Environ.device_type.nil?
47
+
48
+ driver_caps = case Environ.driver
49
+ when :appium
50
+ appium_local_capabilities
51
+ when :custom
52
+ raise 'User-defined cloud driver requires that you define options' if options.nil?
53
+ custom_capabilities
54
+ when :browserstack
55
+ browserstack_capabilities
56
+ when :testingbot
57
+ testingbot_capabilities
58
+ # :nocov:
59
+ when :saucelabs
60
+ sauce_capabilities
61
+ else
62
+ raise "#{Environ.driver} is not a supported driver"
63
+ # :nocov:
64
+ end
65
+ driver_opts = {
66
+ caps: driver_caps,
67
+ appium_lib: { server_url: @endpoint }
68
+ }
69
+ @driver = Appium::Driver.new(driver_opts, global_driver = @global_scope)
70
+ @driver.start_driver
71
+ Environ.appium_driver = @driver
72
+ @running = true
73
+ Appium.promote_appium_methods(TestCentricity::ScreenObject, driver = @driver)
74
+ Appium.promote_appium_methods(TestCentricity::ScreenSection, driver = @driver)
75
+ Appium.promote_appium_methods(TestCentricity::AppElements::AppUIElement, driver = @driver)
76
+
77
+ Environ.screen_size = window_size
78
+ unless Environ.driver_name
79
+ Environ.driver_name = "#{Environ.driver}_#{Environ.device_os}_#{Environ.device_type}".downcase.to_sym
80
+ end
81
+ Environ.session_state = :running
82
+ end
83
+
84
+ # Quit the running driver instance. Sets Environ.session_state to :quit.
85
+ #
86
+ def self.quit_driver
87
+ if @running
88
+ driver.driver_quit
89
+ @running = false
90
+ end
91
+ Environ.session_state = :quit
92
+ end
93
+
94
+ # Return a reference to last created Appium driver
95
+ #
96
+ def self.driver
97
+ @driver
98
+ end
99
+
100
+ # Save a screenshot in .png format to the specified file path.
101
+ #
102
+ # @param png_save_path [String] path to save the screenshot
103
+ # @example
104
+ # AppiumConnect.take_screenshot('reports/screenshots/login_screen.png')
105
+ #
106
+ def self.take_screenshot(png_save_path)
107
+ FileUtils.mkdir_p(File.dirname(png_save_path))
108
+ driver.driver.save_screenshot(png_save_path)
109
+ end
110
+
111
+ # Install app on device. If bundle_id is not specified, then bundle id will be retrieved from Environ.current.ios_bundle_id
112
+ # or Environ.current.android_app_id dependent on which platform is being tested.
113
+ #
114
+ # @param bundle_id [String] OPTIONAL bundle id of app
115
+ # @example
116
+ # AppiumConnect.install_app('com.saucelabs.mydemoapp.rn')
117
+ #
118
+ def self.install_app(app_path)
119
+ driver.install_app(app_path)
120
+ end
121
+
122
+ # Remove app from device. If bundle_id is not specified, then bundle id will be retrieved from Environ.current.ios_bundle_id
123
+ # or Environ.current.android_app_id dependent on which platform is being tested.
124
+ #
125
+ # @param bundle_id [String] OPTIONAL bundle id of app
126
+ # @example
127
+ # AppiumConnect.remove_app('com.saucelabs.mydemoapp.rn')
128
+ #
129
+ def self.remove_app(bundle_id = nil)
130
+ driver.remove_app(get_app_id(bundle_id))
131
+ end
132
+
133
+ # Is the app installed? If bundle_id is not specified, then bundle id will be retrieved from Environ.current.ios_bundle_id
134
+ # or Environ.current.android_app_id dependent on which platform is being tested.
135
+ #
136
+ # @param bundle_id [String] OPTIONAL bundle id of app
137
+ # @return [Boolean] TRUE if app is installed
138
+ # @example
139
+ # AppiumConnect.app_installed?('com.saucelabs.mydemoapp.rn')
140
+ #
141
+ def self.app_installed?(bundle_id = nil)
142
+ driver.app_installed?(get_app_id(bundle_id))
143
+ end
144
+
145
+ # Backgrounds the app for a specified number of seconds.
146
+ #
147
+ # @param duration [Integer] number of seconds to background the app for
148
+ # @example
149
+ # AppiumConnect.background_app(20)
150
+ #
151
+ def self.background_app(duration = 0)
152
+ driver.background_app(duration)
153
+ end
154
+
155
+ # Launch the app. If bundle_id is not specified, then bundle id will be retrieved from Environ.current.ios_bundle_id,
156
+ # Environ.current.android_app_id, or Environ.current.mac_bundle_id dependent on which platform is being tested.
157
+ #
158
+ # @param bundle_id [String] OPTIONAL bundle id of app
159
+ # @example
160
+ # AppiumConnect.activate_app('com.saucelabs.mydemoapp.rn')
161
+ #
162
+ def self.activate_app(bundle_id = nil)
163
+ if Environ.is_macos?
164
+ @driver.execute_script('macos: activateApp', { bundleId: get_app_id(bundle_id) })
165
+ else
166
+ driver.activate_app(get_app_id(bundle_id))
167
+ if Environ.is_android?
168
+ sleep(1.5) if app_state == :running_in_foreground
169
+ end
170
+ end
171
+ Environ.new_app_session
172
+ end
173
+
174
+ # Get status of app. If bundle_id is not specified, then bundle id will be retrieved from Environ.current.ios_bundle_id,
175
+ # Environ.current.android_app_id, or Environ.current.mac_bundle_id dependent on which platform is being tested. Returns
176
+ # the following statuses:
177
+ # :not_installed - The current application state cannot be determined/is unknown
178
+ # :not_running - The application is not running
179
+ # :running_in_background_suspended - The application is running in the background and is suspended
180
+ # :running_in_background - The application is running in the background and is not suspended
181
+ # :running_in_foreground - The application is running in the foreground
182
+ #
183
+ # @param bundle_id [String] OPTIONAL bundle id of app
184
+ # @return [Symbol] status of app
185
+ # @example
186
+ # AppiumConnect.app_state('com.saucelabs.mydemoapp.rn')
187
+ #
188
+ def self.app_state(bundle_id = nil)
189
+ if Environ.is_macos?
190
+ state = @driver.execute_script('macos: queryAppState', { bundleId: get_app_id(bundle_id) })
191
+ case state
192
+ when 0
193
+ :not_installed
194
+ when 1
195
+ :not_running
196
+ when 2
197
+ :running_in_background_suspended
198
+ when 3
199
+ :running_in_background
200
+ when 4
201
+ :running_in_foreground
202
+ end
203
+ else
204
+ driver.app_state(get_app_id(bundle_id))
205
+ end
206
+ end
207
+
208
+ # Terminate the app. If bundle_id is not specified, then bundle id will be retrieved from Environ.current.ios_bundle_id,
209
+ # Environ.current.android_app_id, or Environ.current.mac_bundle_id dependent on which platform is being tested.
210
+ #
211
+ # @param bundle_id [String] OPTIONAL bundle id of app
212
+ # @example
213
+ # AppiumConnect.terminate_app('com.saucelabs.mydemoapp.rn')
214
+ #
215
+ def self.terminate_app(bundle_id = nil)
216
+ if Environ.is_macos?
217
+ @driver.execute_script('macos: terminateApp', { bundleId: get_app_id(bundle_id) })
218
+ else
219
+ driver.terminate_app(get_app_id(bundle_id))
220
+ end
221
+ end
222
+
223
+ # Set the amount of time the driver should wait when searching for elements.
224
+ #
225
+ # @param timeout [Integer] number of seconds to wait
226
+ #
227
+ def self.implicit_wait(timeout)
228
+ driver.manage.timeouts.implicit_wait = timeout
229
+ end
230
+
231
+ # Hide the onscreen keyboard
232
+ #
233
+ def self.hide_keyboard
234
+ driver.hide_keyboard
235
+ end
236
+
237
+ # Is onscreen keyboard displayed?
238
+ #
239
+ # @return [Boolean] TRUE if keyboard is shown. Return false if keyboard is hidden.
240
+ #
241
+ def self.keyboard_shown?
242
+ @driver.execute_script('mobile: isKeyboardShown')
243
+ end
244
+
245
+ # Get the current screen orientation
246
+ #
247
+ # @return [Symbol] :landscape or :portrait
248
+ #
249
+ def self.orientation
250
+ driver.driver.orientation
251
+ end
252
+
253
+ # Change the screen orientation
254
+ #
255
+ # @param orientation [Symbol or String] :landscape or :portrait
256
+ #
257
+ def self.rotation(orientation)
258
+ orientation.downcase.to_sym if orientation.is_a?(String)
259
+ driver.driver.rotation = orientation
260
+ end
261
+
262
+ # Get the device's window size.
263
+ #
264
+ # @return [Array] window size as [width, height]
265
+ #
266
+ def self.window_size
267
+ size = driver.window_size
268
+ [size.width, size.height]
269
+ end
270
+
271
+ # Get the device's window rectangle.
272
+ #
273
+ # @return (Selenium::WebDriver::Rectangle)
274
+ #
275
+ def self.window_rect
276
+ driver.window_rect
277
+ end
278
+
279
+ def self.geolocation
280
+ driver.driver.location
281
+ end
282
+
283
+ def self.set_geolocation(location_data)
284
+ driver.set_location(location_data)
285
+ end
286
+
287
+ def self.current_context
288
+ driver.current_context
289
+ end
290
+
291
+ def self.set_context(context)
292
+ driver.set_context(context)
293
+ end
294
+
295
+ def self.available_contexts
296
+ driver.available_contexts
297
+ end
298
+
299
+ def self.is_webview?
300
+ driver.current_context.start_with?('WEBVIEW')
301
+ end
302
+
303
+ def self.is_native_app?
304
+ driver.current_context.start_with?('NATIVE_APP')
305
+ end
306
+
307
+ def self.webview_context
308
+ contexts = driver.available_contexts
309
+ puts "Contexts = #{contexts}" if ENV['DEBUG']
310
+ set_context(contexts.last)
311
+ puts "Current context = #{driver.current_context}" if ENV['DEBUG']
312
+ end
313
+
314
+ def self.is_biometric_enrolled?
315
+ if Environ.is_ios?
316
+ @driver.execute_script('mobile: isBiometricEnrolled')
317
+ else
318
+ puts 'biometric_enrollment is not supported for this platform'
319
+ end
320
+ end
321
+
322
+ def self.set_biometric_enrollment(state)
323
+ if Environ.is_ios?
324
+ @driver.execute_script('mobile: enrollBiometric', { isEnabled: state })
325
+ else
326
+ puts 'biometric_enrollment is not supported for this platform'
327
+ end
328
+ end
329
+
330
+ def self.biometric_match(type, match)
331
+ if Environ.is_ios?
332
+ @driver.execute_script('mobile: sendBiometricMatch', { type: type, match: match })
333
+ else
334
+ raise 'biometric_match is not supported for this platform'
335
+ end
336
+ end
337
+
338
+ # :nocov:
339
+ def self.upload_app(service)
340
+ # determine app custom test id (if specified)
341
+ custom_id = if ENV['APP_ID']
342
+ ENV['APP_ID']
343
+ else
344
+ Environ.is_android? ? Environ.current.android_test_id : Environ.current.ios_test_id
345
+ end
346
+ # determine endpoint url, user id, and auth key for specified cloud service provider
347
+ case service
348
+ when :browserstack
349
+ url = 'https://api-cloud.browserstack.com/app-automate/upload'
350
+ user_id = ENV['BS_USERNAME']
351
+ auth_key = ENV['BS_AUTHKEY']
352
+ when :testingbot
353
+ url = 'https://api.testingbot.com/v1/storage'
354
+ url = "#{url}/#{custom_id}" unless custom_id.nil?
355
+ user_id = ENV['TB_USERNAME']
356
+ auth_key = ENV['TB_AUTHKEY']
357
+ else
358
+ raise "#{service} is not supported"
359
+ end
360
+ # determine file path of app to be uploaded to cloud service
361
+ file_path = if Environ.is_android?
362
+ Environ.current.android_apk_path
363
+ elsif Environ.is_ios?
364
+ Environ.is_device? ? Environ.current.ios_ipa_path : Environ.current.ios_app_path
365
+ end
366
+
367
+ request = Net::HTTP::Post.new(url)
368
+ boundary = "WebAppBoundary"
369
+ post_body = []
370
+ post_body << "--#{boundary}\r\n"
371
+ post_body << "Content-Disposition: form-data; name=\"file\"; filename=\"#{file_path}\"\r\n"
372
+ post_body << "\r\n"
373
+ post_body << File.open(file_path) {|io| io.read}
374
+ # add custom id form data to post body if a custom test id has been provided
375
+ if !custom_id.nil? && service == :browserstack
376
+ post_body << "\r\n--#{boundary}\r\n"
377
+ post_body << "Content-Disposition: form-data; name=\"custom_id\"\r\n"
378
+ post_body << "\r\n"
379
+ post_body << "#{custom_id}"
380
+ end
381
+ post_body << "\r\n--#{boundary}--\r\n"
382
+ request.body = post_body.join
383
+ request["Content-Type"] = "multipart/form-data; boundary=#{boundary}"
384
+ request.basic_auth(user_id, auth_key)
385
+ # send the request to upload to cloud service provider
386
+ uri = URI.parse(url)
387
+ conn = Net::HTTP.new(uri.host, uri.port)
388
+ if uri.scheme == 'https'
389
+ conn.use_ssl = true
390
+ conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
391
+ end
392
+ response = conn.request(request)
393
+ result = JSON.parse(response.body)
394
+ if response.code.to_i > 202
395
+ raise "An error has occurred while attempting to upload #{file_path} to the #{service} service\n#{result}"
396
+ else
397
+ puts "Successfully uploaded #{file_path} to the #{service} service\n#{result}"
398
+ end
399
+ end
400
+ # :nocov:
401
+
402
+ private
403
+
404
+ def self.get_app_id(bundle_id = nil)
405
+ return bundle_id unless bundle_id.nil?
406
+ case
407
+ when Environ.is_ios?
408
+ Environ.current.ios_bundle_id
409
+ when Environ.is_android?
410
+ Environ.current.android_app_id
411
+ when Environ.is_macos?
412
+ Environ.current.mac_bundle_id
413
+ else
414
+ nil
415
+ end
416
+ end
417
+
418
+ def self.appium_local_capabilities
419
+ # specify endpoint url
420
+ if @endpoint.nil?
421
+ @endpoint = if ENV['APPIUM_SERVER_VERSION'] && ENV['APPIUM_SERVER_VERSION'].to_i == 1
422
+ 'http://127.0.0.1:4723/wd/hub'
423
+ else
424
+ 'http://127.0.0.1:4723'
425
+ end
426
+ end
427
+ # define local Appium capabilities
428
+ if @capabilities.nil?
429
+ Environ.device_name = ENV['APP_DEVICE']
430
+ Environ.device_os = ENV['APP_PLATFORM_NAME']
431
+ Environ.device_os_version = ENV['APP_VERSION']
432
+ Environ.device = ENV['UDID'] ? :device : :simulator
433
+
434
+ caps = {
435
+ platformName: ENV['APP_PLATFORM_NAME'],
436
+ 'appium:platformVersion': ENV['APP_VERSION'],
437
+ 'appium:deviceName': ENV['APP_DEVICE'],
438
+ 'appium:automationName': ENV['AUTOMATION_ENGINE']
439
+ }
440
+ caps[:'appium:avd'] = ENV['APP_DEVICE'] if ENV['APP_PLATFORM_NAME'].downcase.to_sym == :android
441
+ caps[:'appium:orientation'] = ENV['ORIENTATION'].upcase if ENV['ORIENTATION']
442
+ if ENV['LOCALE'] && ENV['LANGUAGE']
443
+ caps[:'appium:language'] = ENV['LANGUAGE']
444
+ caps[:'appium:locale'] = if Environ.is_android?
445
+ locale = ENV['LOCALE'].gsub('-', '_')
446
+ locale.split('_')[1]
447
+ else
448
+ ENV['LOCALE'].gsub('-', '_')
449
+ end
450
+ end
451
+ caps[:'appium:newCommandTimeout'] = ENV['NEW_COMMAND_TIMEOUT'] if ENV['NEW_COMMAND_TIMEOUT']
452
+ caps[:'appium:noReset'] = ENV['APP_NO_RESET'] if ENV['APP_NO_RESET']
453
+ caps[:'appium:fullReset'] = ENV['APP_FULL_RESET'] if ENV['APP_FULL_RESET']
454
+ caps[:'appium:autoLaunch'] = ENV['AUTO_LAUNCH'] if ENV['AUTO_LAUNCH']
455
+ caps[:'appium:webkitDebugProxyPort'] = ENV['WEBKIT_DEBUG_PROXY_PORT'] if ENV['WEBKIT_DEBUG_PROXY_PORT']
456
+ caps[:'appium:webDriverAgentUrl'] = ENV['WEBDRIVER_AGENT_URL'] if ENV['WEBDRIVER_AGENT_URL']
457
+ caps[:'appium:wdaLocalPort'] = ENV['WDA_LOCAL_PORT'] if ENV['WDA_LOCAL_PORT']
458
+ caps[:'appium:usePrebuiltWDA'] = ENV['USE_PREBUILT_WDA'] if ENV['USE_PREBUILT_WDA']
459
+ caps[:'appium:useNewWDA'] = ENV['USE_NEW_WDA'] if ENV['USE_NEW_WDA']
460
+ caps[:'appium:autoWebview'] = ENV['AUTO_WEBVIEW'] if ENV['AUTO_WEBVIEW']
461
+ caps[:'appium:chromedriverExecutable'] = ENV['CHROMEDRIVER_EXECUTABLE'] if ENV['CHROMEDRIVER_EXECUTABLE']
462
+ caps[:'appium:autoWebviewTimeout'] = ENV['AUTO_WEBVIEW_TIMEOUT'] if ENV['AUTO_WEBVIEW_TIMEOUT']
463
+ caps[:'appium:udid'] = ENV['UDID'] if ENV['UDID']
464
+ caps[:'appium:xcodeOrgId'] = ENV['TEAM_ID'] if ENV['TEAM_ID']
465
+ caps[:'appium:xcodeSigningId'] = ENV['TEAM_NAME'] if ENV['TEAM_NAME']
466
+ caps[:'appium:appActivity'] = ENV['APP_ACTIVITY'] if ENV['APP_ACTIVITY']
467
+ caps[:'appium:appPackage'] = ENV['APP_PACKAGE'] if ENV['APP_PACKAGE']
468
+ caps[:'appium:forceSimulatorSoftwareKeyboardPresence'] = ENV['SHOW_SIM_KEYBOARD'] if ENV['SHOW_SIM_KEYBOARD']
469
+ if Environ.is_ios?
470
+ caps[:'appium:webviewConnectTimeout'] = 90000
471
+ caps[:'appium:maxTypingFrequency'] = 15
472
+ caps[:'appium:respectSystemAlerts'] = true
473
+ end
474
+
475
+ if ENV['BUNDLE_ID']
476
+ caps[:'appium:bundleId'] = ENV['BUNDLE_ID']
477
+ else
478
+ app_id = get_app_id
479
+ caps[:'appium:bundleId'] = app_id unless app_id.nil?
480
+ end
481
+
482
+ caps[:'appium:app'] = if ENV['APP']
483
+ ENV['APP']
484
+ else
485
+ if Environ.is_android?
486
+ Environ.current.android_apk_path
487
+ elsif Environ.is_ios?
488
+ Environ.is_device? ?
489
+ Environ.current.ios_ipa_path :
490
+ Environ.current.ios_app_path
491
+ end
492
+ end
493
+ caps
494
+ else
495
+ Environ.device_os = @capabilities[:platformName]
496
+ Environ.device_name = @capabilities[:'appium:deviceName']
497
+ Environ.device_os_version = @capabilities[:'appium:platformVersion']
498
+ Environ.device_orientation = @capabilities[:'appium:orientation']
499
+ Environ.device = @capabilities[:'appium:udid'] ? :device : :simulator
500
+ @capabilities
501
+ end
502
+ end
503
+
504
+ def self.custom_capabilities
505
+ raise 'User-defined cloud driver requires that you provide capabilities' if @capabilities.nil?
506
+ raise 'User-defined cloud driver requires that you provide an endpoint' if @endpoint.nil?
507
+
508
+ Environ.device_os = @capabilities[:platformName]
509
+ Environ.device_name = @capabilities[:'appium:deviceName']
510
+ Environ.device_os_version = @capabilities[:'appium:platformVersion']
511
+ @capabilities
512
+ end
513
+
514
+ def self.browserstack_capabilities
515
+ # specify endpoint url
516
+ @endpoint = "https://#{ENV['BS_USERNAME']}:#{ENV['BS_AUTHKEY']}@hub-cloud.browserstack.com/wd/hub" if @endpoint.nil?
517
+ # define BrowserStack options
518
+ options = if @capabilities.nil?
519
+ Environ.device_name = ENV['BS_DEVICE']
520
+ Environ.device_os = ENV['BS_OS']
521
+ Environ.device_os_version = ENV['BS_OS_VERSION']
522
+ # define the required set of BrowserStack options
523
+ bs_options = {
524
+ userName: ENV['BS_USERNAME'],
525
+ accessKey: ENV['BS_AUTHKEY'],
526
+ sessionName: test_context_message
527
+ }
528
+ # define the optional BrowserStack options
529
+ bs_options[:projectName] = ENV['AUTOMATE_PROJECT'] if ENV['AUTOMATE_PROJECT']
530
+ bs_options[:buildName] = ENV['AUTOMATE_BUILD'] if ENV['AUTOMATE_BUILD']
531
+ bs_options[:geoLocation] = ENV['IP_GEOLOCATION'] if ENV['IP_GEOLOCATION']
532
+ bs_options[:timezone] = ENV['TIME_ZONE'] if ENV['TIME_ZONE']
533
+ bs_options[:video] = ENV['RECORD_VIDEO'] if ENV['RECORD_VIDEO']
534
+ bs_options[:debug] = ENV['SCREENSHOTS'] if ENV['SCREENSHOTS']
535
+ bs_options[:local] = ENV['TUNNELING'] if ENV['TUNNELING']
536
+ bs_options[:deviceOrientation] = ENV['ORIENTATION'] if ENV['ORIENTATION']
537
+ bs_options[:appiumLogs] = ENV['APPIUM_LOGS'] if ENV['APPIUM_LOGS']
538
+ bs_options[:networkLogs] = ENV['NETWORK_LOGS'] if ENV['NETWORK_LOGS']
539
+ bs_options[:deviceLogs] = ENV['DEVICE_LOGS'] if ENV['DEVICE_LOGS']
540
+ bs_options[:networkProfile] = ENV['NETWORK_PROFILE'] if ENV['NETWORK_PROFILE']
541
+ bs_options[:idleTimeout] = ENV['IDLE_TIMEOUT'] if ENV['IDLE_TIMEOUT']
542
+ bs_options[:resignApp] = ENV['RESIGN_APP'] if ENV['RESIGN_APP']
543
+ bs_options[:gpsLocation] = ENV['GPS_LOCATION'] if ENV['GPS_LOCATION']
544
+ bs_options[:acceptInsecureCerts] = ENV['ACCEPT_INSECURE_CERTS'] if ENV['ACCEPT_INSECURE_CERTS']
545
+ bs_options[:disableAnimations] = ENV['DISABLE_ANIMATION'] if ENV['DISABLE_ANIMATION']
546
+ bs_options[:appiumVersion] = ENV['APPIUM_VERSION'] ? ENV['APPIUM_VERSION'] : '2.4.1'
547
+
548
+ capabilities = {
549
+ platformName: ENV['BS_OS'],
550
+ 'appium:platformVersion': ENV['BS_OS_VERSION'],
551
+ 'appium:deviceName': ENV['BS_DEVICE'],
552
+ 'appium:automationName': ENV['AUTOMATION_ENGINE'],
553
+ 'appium:app': ENV['APP'],
554
+ 'bstack:options': bs_options
555
+ }
556
+ capabilities[:language] = ENV['LANGUAGE'] if ENV['LANGUAGE']
557
+ capabilities[:locale] = ENV['LOCALE'] if ENV['LOCALE']
558
+ capabilities
559
+ else
560
+ Environ.device_os = @capabilities[:platformName]
561
+ Environ.device_name = @capabilities[:'appium:deviceName']
562
+ Environ.device_os_version = @capabilities[:'appium:platformVersion']
563
+ @capabilities
564
+ end
565
+ # BrowserStack uses only real devices
566
+ Environ.device = :device
567
+ upload_app(:browserstack) if ENV['UPLOAD_APP']
568
+ options
569
+ end
570
+
571
+ # :nocov:
572
+ def self.testingbot_capabilities
573
+ Environ.device = :simulator
574
+ # specify endpoint url
575
+ @endpoint = "http://#{ENV['TB_USERNAME']}:#{ENV['TB_AUTHKEY']}@hub.testingbot.com/wd/hub" if @endpoint.nil?
576
+ # define TestingBot options
577
+ options = if @capabilities.nil?
578
+ Environ.device_name = ENV['TB_DEVICE']
579
+ Environ.device_os = ENV['TB_OS']
580
+ Environ.device_os_version = ENV['TB_OS_VERSION']
581
+ Environ.device = :device if ENV['REAL_DEVICE'] == 'true'
582
+ # define the required set of TestingBot options
583
+ tb_options = { build: test_context_message }
584
+ # define the optional TestingBot options
585
+ tb_options[:name] = ENV['AUTOMATE_PROJECT'] if ENV['AUTOMATE_PROJECT']
586
+ tb_options[:timeZone] = ENV['TIME_ZONE'] if ENV['TIME_ZONE']
587
+ tb_options['testingbot.geoCountryCode'] = ENV['IP_GEOLOCATION'] if ENV['IP_GEOLOCATION']
588
+ tb_options[:screenrecorder] = ENV['RECORD_VIDEO'] if ENV['RECORD_VIDEO']
589
+ tb_options[:screenshot] = ENV['SCREENSHOTS'] if ENV['SCREENSHOTS']
590
+ tb_options[:appiumVersion] = ENV['APPIUM_VERSION'] ? ENV['APPIUM_VERSION'] : '2.4.1'
591
+
592
+ capabilities = {
593
+ platformName: ENV['TB_OS'],
594
+ 'appium:platformVersion': ENV['TB_OS_VERSION'],
595
+ 'appium:deviceName': ENV['TB_DEVICE'],
596
+ 'appium:automationName': ENV['AUTOMATION_ENGINE'],
597
+ 'appium:app': ENV['APP'],
598
+ 'tb:options': tb_options
599
+ }
600
+ capabilities[:'appium:realDevice'] = ENV['REAL_DEVICE'] if ENV['REAL_DEVICE']
601
+ capabilities
602
+ else
603
+ Environ.device_os = @capabilities[:platformName]
604
+ Environ.device_name = @capabilities[:'appium:deviceName']
605
+ Environ.device_os_version = @capabilities[:'appium:platformVersion']
606
+ if @capabilities.key?(:'appium:realDevice') && @capabilities[:'appium:realDevice'] == true
607
+ Environ.device = :device
608
+ end
609
+ @capabilities
610
+ end
611
+
612
+ upload_app(:testingbot) if ENV['UPLOAD_APP']
613
+ options
614
+ end
615
+
616
+ def self.sauce_capabilities
617
+ # specify endpoint url
618
+ if @endpoint.nil?
619
+ @endpoint = "https://#{ENV['SL_USERNAME']}:#{ENV['SL_AUTHKEY']}@ondemand.#{ENV['SL_DATA_CENTER']}.saucelabs.com:443/wd/hub"
620
+ end
621
+ # define SauceLabs options
622
+ options = if @capabilities.nil?
623
+ Environ.device_name = ENV['SL_DEVICE']
624
+ Environ.device_os = ENV['SL_OS']
625
+ Environ.device_os_version = ENV['SL_OS_VERSION']
626
+ # define the required set of SauceLabs options
627
+ sl_options = { build: test_context_message }
628
+ # define the optional SauceLabs options
629
+ sl_options[:name] = ENV['AUTOMATE_PROJECT'] if ENV['AUTOMATE_PROJECT']
630
+ sl_options[:deviceOrientation] = ENV['ORIENTATION'].upcase if ENV['ORIENTATION']
631
+ sl_options[:recordVideo] = ENV['RECORD_VIDEO'] if ENV['RECORD_VIDEO']
632
+ sl_options[:recordScreenshots] = ENV['SCREENSHOTS'] if ENV['SCREENSHOTS']
633
+ sl_options[:appiumVersion] = ENV['APPIUM_VERSION'] ? ENV['APPIUM_VERSION'] : '2.1.3'
634
+ capabilities = {
635
+ platformName: ENV['SL_OS'],
636
+ 'appium:platformVersion': ENV['SL_OS_VERSION'],
637
+ 'appium:deviceName': ENV['SL_DEVICE'],
638
+ 'appium:automationName': ENV['AUTOMATION_ENGINE'],
639
+ 'appium:app': ENV['APP'],
640
+ 'sauce:options': sl_options
641
+ }
642
+ capabilities
643
+ else
644
+ Environ.device_os = @capabilities[:platformName]
645
+ Environ.device_name = @capabilities[:'appium:deviceName']
646
+ Environ.device_os_version = @capabilities[:'appium:platformVersion']
647
+ @capabilities
648
+ end
649
+ options
650
+ end
651
+
652
+ def self.test_context_message
653
+ context_message = if ENV['TEST_CONTEXT']
654
+ "#{Environ.test_environment.to_s.upcase} - #{ENV['TEST_CONTEXT']}"
655
+ else
656
+ Environ.test_environment.to_s.upcase
657
+ end
658
+ if ENV['PARALLEL']
659
+ thread_num = ENV['TEST_ENV_NUMBER']
660
+ thread_num = 1 if thread_num.blank?
661
+ context_message = "#{context_message} - Thread ##{thread_num}"
662
+ end
663
+ context_message
664
+ end
665
+ # :nocov:
666
+ end
667
+ end