bugsnag-maze-runner 6.27.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/bin/bugsnag-print-load-paths +6 -0
  3. data/bin/download-logs +76 -0
  4. data/bin/maze-runner +136 -0
  5. data/bin/upload-app +56 -0
  6. data/lib/features/scripts/await-android-emulator.sh +11 -0
  7. data/lib/features/scripts/clear-android-app-data.sh +8 -0
  8. data/lib/features/scripts/force-stop-android-app.sh +8 -0
  9. data/lib/features/scripts/install-android-app.sh +15 -0
  10. data/lib/features/scripts/launch-android-app.sh +38 -0
  11. data/lib/features/scripts/launch-android-emulator.sh +15 -0
  12. data/lib/features/steps/android_steps.rb +51 -0
  13. data/lib/features/steps/app_automator_steps.rb +228 -0
  14. data/lib/features/steps/aws_sam_steps.rb +212 -0
  15. data/lib/features/steps/breadcrumb_steps.rb +50 -0
  16. data/lib/features/steps/browser_steps.rb +93 -0
  17. data/lib/features/steps/build_api_steps.rb +25 -0
  18. data/lib/features/steps/document_server_steps.rb +7 -0
  19. data/lib/features/steps/error_reporting_steps.rb +342 -0
  20. data/lib/features/steps/feature_flag_steps.rb +190 -0
  21. data/lib/features/steps/header_steps.rb +72 -0
  22. data/lib/features/steps/log_steps.rb +29 -0
  23. data/lib/features/steps/multipart_request_steps.rb +142 -0
  24. data/lib/features/steps/network_steps.rb +75 -0
  25. data/lib/features/steps/payload_steps.rb +234 -0
  26. data/lib/features/steps/proxy_steps.rb +34 -0
  27. data/lib/features/steps/query_parameter_steps.rb +31 -0
  28. data/lib/features/steps/request_assertion_steps.rb +107 -0
  29. data/lib/features/steps/runner_steps.rb +406 -0
  30. data/lib/features/steps/session_tracking_steps.rb +116 -0
  31. data/lib/features/steps/value_steps.rb +119 -0
  32. data/lib/features/support/env.rb +7 -0
  33. data/lib/features/support/internal_hooks.rb +260 -0
  34. data/lib/maze/appium_server.rb +112 -0
  35. data/lib/maze/assertions/request_set_assertions.rb +97 -0
  36. data/lib/maze/aws/sam.rb +112 -0
  37. data/lib/maze/bitbar_devices.rb +84 -0
  38. data/lib/maze/bitbar_utils.rb +112 -0
  39. data/lib/maze/browser_stack_devices.rb +160 -0
  40. data/lib/maze/browser_stack_utils.rb +164 -0
  41. data/lib/maze/browsers_bs.yml +220 -0
  42. data/lib/maze/browsers_cbt.yml +100 -0
  43. data/lib/maze/bugsnag_config.rb +42 -0
  44. data/lib/maze/capabilities.rb +126 -0
  45. data/lib/maze/checks/assert_check.rb +91 -0
  46. data/lib/maze/checks/noop_check.rb +34 -0
  47. data/lib/maze/compare.rb +161 -0
  48. data/lib/maze/configuration.rb +174 -0
  49. data/lib/maze/docker.rb +108 -0
  50. data/lib/maze/document_server.rb +46 -0
  51. data/lib/maze/driver/appium.rb +217 -0
  52. data/lib/maze/driver/browser.rb +138 -0
  53. data/lib/maze/driver/resilient_appium.rb +51 -0
  54. data/lib/maze/errors.rb +20 -0
  55. data/lib/maze/helper.rb +118 -0
  56. data/lib/maze/hooks/appium_hooks.rb +216 -0
  57. data/lib/maze/hooks/browser_hooks.rb +68 -0
  58. data/lib/maze/hooks/command_hooks.rb +9 -0
  59. data/lib/maze/hooks/hooks.rb +61 -0
  60. data/lib/maze/interactive_cli.rb +173 -0
  61. data/lib/maze/logger.rb +73 -0
  62. data/lib/maze/macos_utils.rb +14 -0
  63. data/lib/maze/network.rb +49 -0
  64. data/lib/maze/option/parser.rb +245 -0
  65. data/lib/maze/option/processor.rb +143 -0
  66. data/lib/maze/option/validator.rb +184 -0
  67. data/lib/maze/option.rb +64 -0
  68. data/lib/maze/plugins/bugsnag_reporting_plugin.rb +49 -0
  69. data/lib/maze/plugins/cucumber_report_plugin.rb +101 -0
  70. data/lib/maze/plugins/global_retry_plugin.rb +38 -0
  71. data/lib/maze/proxy.rb +114 -0
  72. data/lib/maze/request_list.rb +82 -0
  73. data/lib/maze/retry_handler.rb +76 -0
  74. data/lib/maze/runner.rb +149 -0
  75. data/lib/maze/sauce_labs_utils.rb +96 -0
  76. data/lib/maze/server.rb +207 -0
  77. data/lib/maze/servlets/base_servlet.rb +22 -0
  78. data/lib/maze/servlets/command_servlet.rb +44 -0
  79. data/lib/maze/servlets/log_servlet.rb +64 -0
  80. data/lib/maze/servlets/reflective_servlet.rb +69 -0
  81. data/lib/maze/servlets/servlet.rb +160 -0
  82. data/lib/maze/smart_bear_utils.rb +71 -0
  83. data/lib/maze/store.rb +15 -0
  84. data/lib/maze/terminating_server.rb +129 -0
  85. data/lib/maze/timers.rb +51 -0
  86. data/lib/maze/wait.rb +35 -0
  87. data/lib/maze.rb +27 -0
  88. metadata +371 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 508b197638d8f5af31b4018fecd9776cfa91071ba760c90ce6647cf720d0bfb0
4
+ data.tar.gz: 3f47abb96bfa76e64a569b06c58d13b229305405e74142da6b9709a5a655d27e
5
+ SHA512:
6
+ metadata.gz: 5ad71748e2a4ee9a83c65b1192ebd3a5cbfe6c7ee31ef63cdff5ea78674c130315946cd784004c8a0b0f0bfaf21fbf4e71c8277ca94b9a036bf88f7b36781538
7
+ data.tar.gz: bec09abd2c07c745d561a3ffc84653b07d792614a5070af2b7fbecc88f5f4a2b720e0bdae2a4e430d872a86885432e3552837b6f1542e92c9e0226949362ad7d
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ CUKE_LOAD_DIR = File.expand_path(File.dirname(File.dirname(__FILE__)))
4
+
5
+ paths = Dir.glob("#{CUKE_LOAD_DIR}/lib/features/**/*.rb")
6
+ print paths.join(" ")
data/bin/download-logs ADDED
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/maze'
5
+ require_relative '../lib/maze/browser_stack_utils'
6
+ require_relative '../lib/maze/logger'
7
+ require 'net/http'
8
+ require 'json'
9
+ require 'uri'
10
+ require 'optimist'
11
+ require 'fileutils'
12
+
13
+ class DownloadLogEntry
14
+ def start(args)
15
+ p = Optimist::Parser.new do
16
+ text 'Download device sessions logs from BrowserStack using the build ID'
17
+ text ''
18
+ text 'Requires BROWSER_STACK_USERNAME and BROWSER_STACK_ACCESS_KEY'
19
+ text ''
20
+ text 'Usage [OPTIONS] <filenames>'
21
+ text ''
22
+ opt :help,
23
+ 'Print this help.'
24
+ opt :build_id,
25
+ "ID of the BrowserStack build",
26
+ :type => :string
27
+ end
28
+
29
+ opts = Optimist::with_standard_exception_handling p do
30
+ raise Optimist::HelpNeeded if ARGV.empty? # show help screen
31
+ p.parse ARGV
32
+ end
33
+
34
+ # Get browserstack username and access key from the environment
35
+ username = ENV['BROWSER_STACK_USERNAME']
36
+ access_key = ENV['BROWSER_STACK_ACCESS_KEY']
37
+
38
+ # Check if BROWSER_STACK_USERNAME or BROWSER_STACK_ACCESS_KEY has been set
39
+ if username.nil? || access_key.nil?
40
+ $logger.warn "BROWSER_STACK_USERNAME or BROWSER_STACK_ACCESS_KEY has not been set"
41
+ Optimist::with_standard_exception_handling p do
42
+ raise Optimist::HelpNeeded
43
+ end
44
+ end
45
+
46
+
47
+ build_info = Maze::BrowserStackUtils.build_info username,
48
+ access_key,
49
+ opts[:build_id]
50
+
51
+ $logger.info "Getting logs for build: #{opts[:build_id]}"
52
+
53
+ build_info.each_with_index do |session, index|
54
+ $logger.info "Downloading Device Logs for Session: #{index + 1} to #{Dir.pwd}/maze_output"
55
+
56
+ log_name = "#{opts[:build_id]}-#{index + 1}"
57
+
58
+ Maze::BrowserStackUtils.download_log username,
59
+ access_key,
60
+ log_name,
61
+ session['automation_session']['device_logs_url'],
62
+ :device
63
+
64
+ $logger.info "Downloading Appium Logs for Session: #{index + 1}"
65
+ Maze::BrowserStackUtils.download_log username,
66
+ access_key,
67
+ log_name,
68
+ session['automation_session']['appium_logs_url'],
69
+ :appium
70
+
71
+
72
+ end
73
+ end
74
+ end
75
+
76
+ DownloadLogEntry.new.start(ARGV)
data/bin/maze-runner ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'cucumber/cli/main'
5
+
6
+ require_relative '../lib/maze'
7
+
8
+ require_relative '../lib/maze/appium_server'
9
+ require_relative '../lib/maze/bitbar_utils'
10
+ require_relative '../lib/maze/bitbar_devices'
11
+ require_relative '../lib/maze/browser_stack_devices'
12
+ require_relative '../lib/maze/browser_stack_utils'
13
+ require_relative '../lib/maze/bugsnag_config'
14
+ require_relative '../lib/maze/capabilities'
15
+ require_relative '../lib/maze/compare'
16
+ require_relative '../lib/maze/docker'
17
+ require_relative '../lib/maze/document_server'
18
+ require_relative '../lib/maze/errors'
19
+ require_relative '../lib/maze/helper'
20
+ require_relative '../lib/maze/logger'
21
+ require_relative '../lib/maze/macos_utils'
22
+ require_relative '../lib/maze/network'
23
+ require_relative '../lib/maze/proxy'
24
+ require_relative '../lib/maze/retry_handler'
25
+ require_relative '../lib/maze/runner'
26
+ require_relative '../lib/maze/sauce_labs_utils'
27
+ require_relative '../lib/maze/smart_bear_utils'
28
+ require_relative '../lib/maze/terminating_server'
29
+
30
+ require_relative '../lib/maze/servlets/base_servlet'
31
+ require_relative '../lib/maze/servlets/command_servlet'
32
+ require_relative '../lib/maze/servlets/servlet'
33
+ require_relative '../lib/maze/servlets/log_servlet'
34
+ require_relative '../lib/maze/servlets/reflective_servlet'
35
+ require_relative '../lib/maze/server'
36
+
37
+ require_relative '../lib/maze/store'
38
+ require_relative '../lib/maze/timers'
39
+
40
+ require_relative '../lib/maze/checks/noop_check'
41
+ require_relative '../lib/maze/checks/assert_check'
42
+
43
+ require_relative '../lib/maze/option'
44
+ require_relative '../lib/maze/option/parser'
45
+ require_relative '../lib/maze/option/processor'
46
+ require_relative '../lib/maze/option/validator'
47
+
48
+
49
+ require_relative '../lib/maze/assertions/request_set_assertions'
50
+
51
+ require_relative '../lib/maze/hooks/hooks'
52
+ require_relative '../lib/maze/hooks/appium_hooks'
53
+ require_relative '../lib/maze/hooks/browser_hooks'
54
+ require_relative '../lib/maze/hooks/command_hooks'
55
+
56
+ require_relative '../lib/maze/driver/appium'
57
+ require_relative '../lib/maze/driver/browser'
58
+ require_relative '../lib/maze/driver/resilient_appium'
59
+
60
+ require_relative '../lib/maze/plugins/bugsnag_reporting_plugin'
61
+ require_relative '../lib/maze/plugins/cucumber_report_plugin'
62
+ require_relative '../lib/maze/plugins/global_retry_plugin'
63
+
64
+ # Encapsulates the MazeRunner entry point
65
+ class MazeRunnerEntry
66
+
67
+ # Removes Maze Runner specific args from the array, as these will cause Cucumber to error.
68
+ def remove_maze_runner_args
69
+ Maze::Option.constants.each do |opt|
70
+ name = Maze::Option.const_get(opt)
71
+ @args.reject! { |arg| arg == "--#{name}" || (arg.start_with? "--#{name}=") || arg == "--no-#{name}" }
72
+ end
73
+ end
74
+
75
+ # Adds arguments to Cucumber
76
+ def add_cucumber_args
77
+ @args << 'features' if @args.empty?
78
+ @args << '--publish-quiet'
79
+ @args << '--color'
80
+
81
+ # Pass strict mode options through to cucumber if present
82
+ # If not we default to strict for undefined and pending results,
83
+ # but no-strict for flaky in order to allow retries
84
+ regex = /--(no-)?strict(-(undefined|pending|flaky))?/
85
+ if @args.all? { |arg| regex.match(arg).nil? }
86
+ @args << '--strict-undefined' << '--strict-pending' << '--no-strict-flaky'
87
+ end
88
+
89
+ # Load internal steps and helper functions
90
+ load_dir = File.expand_path(File.dirname(File.dirname(__FILE__))).freeze
91
+ paths = Dir.glob("#{load_dir}/lib/features/**/*.rb")
92
+
93
+ # Load project-specific steps and helper functions
94
+ paths += Dir.glob('features/{support,steps}/*.rb')
95
+ paths.each { |path| @args << '-r' << path }
96
+ end
97
+
98
+ # List devices for the given device farm, or all otherwise
99
+
100
+ def start(args)
101
+ $logger.info "Maze Runner v#{Maze::VERSION}"
102
+
103
+ # Parse args, processing any Maze Runner specific options
104
+ @args = args.dup
105
+ options = Maze::Option::Parser.parse args
106
+
107
+ if options[Maze::Option::LIST_DEVICES]
108
+ case options[Maze::Option::FARM]
109
+ when :bs
110
+ Maze::BrowserStackDevices.list_devices('ios')
111
+ Maze::BrowserStackDevices.list_devices('android')
112
+ else
113
+ Maze::BrowserStackDevices.list_devices('ios')
114
+ Maze::BrowserStackDevices.list_devices('android')
115
+ end
116
+ exit 0
117
+ end
118
+
119
+ # Validate CL options
120
+ errors = Maze::Option::Validator.new.validate options
121
+ unless errors.empty?
122
+ puts errors
123
+ exit 1
124
+ end
125
+
126
+ Maze::Option::Processor.populate Maze.config, options
127
+
128
+ # Adjust CL options before calling down to Cucumber
129
+ remove_maze_runner_args
130
+ add_cucumber_args
131
+
132
+ Cucumber::Cli::Main.new(@args).execute!
133
+ end
134
+ end
135
+
136
+ MazeRunnerEntry.new.start(ARGV)
data/bin/upload-app ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/maze'
5
+ require_relative '../lib/maze/browser_stack_utils'
6
+ require_relative '../lib/maze/logger'
7
+ require_relative '../lib/maze/helper'
8
+ require 'optimist'
9
+ require 'uri'
10
+ require 'net/http'
11
+
12
+ class UploadAppEntry
13
+ def start(args)
14
+ p = Optimist::Parser.new do
15
+ text 'Upload app files to BrowserStack'
16
+ text ''
17
+ text 'Requires BROWSER_STACK_USERNAME and BROWSER_STACK_ACCESS_KEY'
18
+ text ''
19
+ text 'Usage [OPTIONS]'
20
+ text ''
21
+ opt :help,
22
+ 'Print this help.'
23
+ opt :app,
24
+ 'The app to upload.',
25
+ :type => :string
26
+ opt :app_id_file,
27
+ 'The file to write the uploaded app ID back to',
28
+ :type => :string
29
+ end
30
+
31
+ opts = Optimist::with_standard_exception_handling p do
32
+ raise Optimist::HelpNeeded if ARGV.empty? # show help screen
33
+ p.parse ARGV
34
+ end
35
+
36
+ # Get browserstack username and access key from the environment
37
+ username = ENV['BROWSER_STACK_USERNAME']
38
+ access_key = ENV['BROWSER_STACK_ACCESS_KEY']
39
+
40
+ # Check if BROWSER_STACK_USERNAME or BROWSER_STACK_ACCESS_KEY has been set
41
+ if username.nil? || access_key.nil?
42
+ $logger.warn "BROWSER_STACK_USERNAME or BROWSER_STACK_ACCESS_KEY has not been set"
43
+ Optimist::with_standard_exception_handling p do
44
+ raise Optimist::HelpNeeded
45
+ end
46
+ end
47
+
48
+ Maze::BrowserStackUtils.upload_app username,
49
+ access_key,
50
+ opts[:app],
51
+ opts[:app_id_file]
52
+
53
+ end
54
+ end
55
+
56
+ UploadAppEntry.new.start(ARGV)
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Wait for device to finish booting
4
+ `adb wait-for-device`
5
+
6
+ while `adb shell getprop sys.boot_completed`.strip != "1"
7
+ puts "Awaiting boot completion..."
8
+ sleep 1
9
+ end
10
+
11
+ puts "Device Ready!"
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+
3
+ if [ -z "$APP_BUNDLE" ]; then
4
+ echo APP_BUNDLE environment variable is not set
5
+ exit 1
6
+ fi
7
+
8
+ adb shell pm clear $APP_BUNDLE
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+
3
+ if [ -z "$APP_BUNDLE" ]; then
4
+ echo APP_BUNDLE environment variable is not set
5
+ exit 1
6
+ fi
7
+
8
+ adb shell am force-stop $APP_BUNDLE
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env bash
2
+
3
+ if [ -z "$APP_BUNDLE" ]; then
4
+ echo APP_BUNDLE environment variable is not set
5
+ exit 1
6
+ fi
7
+ if [ -z "$APK_PATH" ]; then
8
+ echo APK_PATH environment variable is not set
9
+ exit 1
10
+ fi
11
+
12
+ echo "Uninstalling '$APP_BUNDLE'"
13
+ adb uninstall "$APP_BUNDLE"
14
+ echo "Installing '$APK_PATH'"
15
+ adb install "$APK_PATH"
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env bash
2
+
3
+ if [ -z "$APP_BUNDLE" ]; then
4
+ echo APP_BUNDLE environment variable is not set
5
+ exit 1
6
+ fi
7
+
8
+ if [ -z "$APP_ACTIVITY" ]; then
9
+ echo APP_ACTIVITY environment variable is not set
10
+ exit 1
11
+ fi
12
+
13
+ if [ -z "$EVENT_TYPE" ]; then
14
+ echo EVENT_TYPE environment variable is not set
15
+ exit 1
16
+ fi
17
+
18
+ if [ -z "$EVENT_METADATA" ]; then
19
+ EVENT_METADATA="none"
20
+ fi
21
+
22
+ if [ -z "$MOCK_API_PORT" ]; then
23
+ echo MOCK_API_PORT environment variable is not set
24
+ exit 1
25
+ fi
26
+
27
+ if [ -z "$BUGSNAG_API_KEY" ]; then
28
+ echo BUGSNAG_API_KEY environment variable is not set
29
+ exit 1
30
+ fi
31
+ echo "Launching MainActivity with '$EVENT_TYPE'"
32
+ adb shell am start -n "$APP_BUNDLE/$APP_ACTIVITY" \
33
+ --es EVENT_TYPE "$EVENT_TYPE" \
34
+ --es EVENT_METADATA "$EVENT_METADATA" \
35
+ --es BUGSNAG_PORT "$MOCK_API_PORT" \
36
+ --es BUGSNAG_API_KEY "$BUGSNAG_API_KEY"
37
+
38
+ echo "Ran Android Test case"
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env bash
2
+
3
+ if [ -z "$ANDROID_EMULATOR" ]; then
4
+ echo EMULATOR environment variable is not set
5
+ exit 1
6
+ fi
7
+
8
+ if [ -z "$ANDROID_HOME" ]; then
9
+ echo ANDROID_HOME environment variable is not set
10
+ exit 1
11
+ fi
12
+
13
+ echo "Launching $ANDROID_EMULATOR emulator"
14
+ $ANDROID_HOME/emulator/emulator @$ANDROID_EMULATOR -no-boot-anim -noaudio -no-snapshot
15
+
@@ -0,0 +1,51 @@
1
+ # @!group Android steps
2
+
3
+ # Starts an Android emulator available within the local environment
4
+ #
5
+ # @step_input emulator [String] The name of the emulator to start
6
+ When("I start Android emulator {string}") do |emulator|
7
+ steps %Q{
8
+ When I set environment variable "ANDROID_EMULATOR" to "#{emulator}"
9
+ And I run the script "launch-android-emulator.sh"
10
+ And I run the script "await-android-emulator.sh" synchronously
11
+ }
12
+ end
13
+
14
+ # Synchronously clears the data for the test application
15
+ # Requires an ADB connection
16
+ When("I clear the Android app data") do
17
+ step('I run the script "clear-android-app-data.sh" synchronously')
18
+ end
19
+
20
+ # Force stops the test application
21
+ # Requires an ADB connection
22
+ When("I force stop the Android app") do
23
+ step('I run the script "force-stop-android-app.sh" synchronously')
24
+ end
25
+
26
+ # Installs a given bundle from an APK onto a device
27
+ # Requires an ADB connection
28
+ #
29
+ # @step_input bundle [String] The bundle to be installed
30
+ # @step_input filepath [String] The path to the application's .apk
31
+ When("I install the {string} Android app from {string}") do |bundle, filepath|
32
+ steps %Q{
33
+ When I set environment variable "APP_BUNDLE" to "#{bundle}"
34
+ And I set environment variable "APK_PATH" to "#{filepath}"
35
+ And I run the script "install-android-app.sh" synchronously
36
+ }
37
+ end
38
+
39
+ # Starts a specific activity for a given app
40
+ # Requires an ADB connection
41
+ #
42
+ # @step_input app [String] The application name
43
+ # @step_input activity [String] The activity to start
44
+ When("I start the {string} Android app using the {string} activity") do |app, activity|
45
+ steps %Q{
46
+ When I set environment variable "APP_BUNDLE" to "#{app}"
47
+ When I set environment variable "APP_ACTIVITY" to "#{activity}"
48
+ And I run the script "launch-android-app.sh" synchronously
49
+ And I wait for 4 seconds
50
+ }
51
+ end
@@ -0,0 +1,228 @@
1
+ # @!group App Automator steps
2
+
3
+ # Checks a UI element is present
4
+ # Requires a running Appium driver
5
+ #
6
+ # @step_input element_id [String] The locator id
7
+ Given('the element {string} is present') do |element_id|
8
+ present = Maze.driver.wait_for_element(element_id)
9
+ raise Maze::Error::AppiumElementNotFoundError.new("The element #{element_id} could not be found", element_id) unless present
10
+ end
11
+
12
+ # Checks a UI element is present within a specified number of seconds
13
+ # Requires a running Appium driver
14
+ #
15
+ # @step_input element_id [String] The locator id
16
+ # @step_input timeout [Int] The number of seconds to wait before timing out
17
+ Given('the element {string} is present within {int} seconds') do |element_id, timeout|
18
+ present = Maze.driver.wait_for_element(element_id, timeout)
19
+ raise Maze::Error::AppiumElementNotFoundError.new("The element #{element_id} could not be found", element_id) unless present
20
+ end
21
+
22
+ # Clicks a given element
23
+ # Requires a running Appium driver
24
+ #
25
+ # @step_input element_id [String] The locator id
26
+ When('I click the element {string}') do |element_id|
27
+ Maze.driver.click_element(element_id)
28
+ end
29
+
30
+ # Sends the app to the background indefinitely
31
+ # Requires a running Appium driver
32
+ When('I send the app to the background') do
33
+ Maze.driver.background_app(-1)
34
+ end
35
+
36
+ # Sends the app to the background for a number of seconds
37
+ # Requires a running Appium driver
38
+ #
39
+ # @step_input timeout [Integer] The amount of time the app is in the background in seconds
40
+ When('I send the app to the background for {int} second(s)') do |timeout|
41
+ Maze.driver.background_app(timeout)
42
+ end
43
+
44
+ # Clears a given element
45
+ # Requires a running Appium driver
46
+ #
47
+ # @step_input element_id [String] The locator id
48
+ When('I clear the element {string}') do |element_id|
49
+ Maze.driver.clear_element(element_id)
50
+ end
51
+
52
+ # Sends keys to a given element
53
+ # Requires a running Appium driver
54
+ #
55
+ # @step_input keys [String] The keys to send to the element
56
+ # @step_input element_id [String] The locator id
57
+ When('I send the keys {string} to the element {string}') do |keys, element_id|
58
+ Maze.driver.send_keys_to_element(element_id, keys)
59
+ end
60
+
61
+ # Tests that the given payload value is correct for the target BrowserStack platform.
62
+ # This step will assume the expected and payload values are strings.
63
+ # If the step is invoked when a remote BrowserStack device is not in use this step will fail.
64
+ #
65
+ # The DataTable used for this step should have `ios` and `android` in the same row as their expected value:
66
+ # | android | Java.lang.RuntimeException |
67
+ # | ios | NSException |
68
+ #
69
+ # If the expected value is set to "@skip", the check should be skipped
70
+ # If the expected value is set to "@null", the check will be for null
71
+ # If the expected value is set to "@not_null", the check will be for a non-null value
72
+ #
73
+ # @step_input request_type [String] The type of request (error, session, build, etc)
74
+ # @step_input field_path [String] The field to test
75
+ # @step_input platform_values [DataTable] A table of acceptable values for each platform
76
+ Then('the {word} payload field {string} equals the platform-dependent string:') do |request_type, field_path, platform_values|
77
+ test_string_platform_values(request_type, field_path, platform_values)
78
+ end
79
+
80
+ # See `the error payload field {string} equals the platform-dependent string:`
81
+ #
82
+ # @step_input field_path [String] The field to test, prepended with "events.0"
83
+ # @step_input platform_values [DataTable] A table of acceptable values for each platform
84
+ Then('the event {string} equals the platform-dependent string:') do |field_path, platform_values|
85
+ test_string_platform_values('error', "events.0.#{field_path}", platform_values)
86
+ end
87
+
88
+ # Tests that the given payload value is correct for the target BrowserStack platform.
89
+ # This step will assume the expected and payload values are numeric.
90
+ # If the step is invoked when a remote BrowserStack device is not in use this step will fail.
91
+ #
92
+ # The DataTable used for this step should have `ios` and `android` in the same row as their expected value:
93
+ # | android | 1 |
94
+ # | ios | 5.5 |
95
+ #
96
+ # If the expected value is set to "@skip", the check should be skipped
97
+ # If the expected value is set to "@null", the check will be for null
98
+ # If the expected value is set to "@not_null", the check will be for a non-null value
99
+ #
100
+ # @step_input request_type [String] The type of request (error, session, build, etc)
101
+ # @step_input field_path [String] The field to test
102
+ # @step_input platform_values [DataTable] A table of acceptable values for each platform
103
+ Then('the {word} payload field {string} equals the platform-dependent numeric:') do |request_type, field_path, platform_values|
104
+ test_numeric_platform_values(request_type, field_path, platform_values)
105
+ end
106
+
107
+ # See `the payload field {string} equals the platform-dependent numeric:`
108
+ #
109
+ # @step_input field_path [String] The field to test, prepended with "events.0"
110
+ # @step_input platform_values [DataTable] A table of acceptable values for each platform
111
+ Then('the event {string} equals the platform-dependent numeric:') do |field_path, platform_values|
112
+ test_numeric_platform_values('error', "events.0.#{field_path}", platform_values)
113
+ end
114
+
115
+ # Tests that the given payload value is correct for the target BrowserStack platform.
116
+ # This step will assume the expected and payload values are booleans.
117
+ # If the step is invoked when a remote BrowserStack device is not in use this step will fail.
118
+ #
119
+ # The DataTable used for this step should have `ios` and `android` in the same row as their expected value:
120
+ # | android | 1 |
121
+ # | ios | 5 |
122
+ #
123
+ # If the expected value is set to "@skip", the check should be skipped
124
+ # If the expected value is set to "@null", the check will be for null
125
+ # If the expected value is set to "@not_null", the check will be for a non-null value
126
+ #
127
+ # @step_input request_type [String] The type of request (error, session, build, etc)
128
+ # @step_input field_path [String] The field to test
129
+ # @step_input platform_values [DataTable] A table of acceptable values for each platform
130
+ Then('the {word} payload field {string} equals the platform-dependent boolean:') do |request_type, field_path, platform_values|
131
+ test_boolean_platform_values(request_type, field_path, platform_values)
132
+ end
133
+
134
+ # See `the payload field {string} equals the platform-dependent boolean:`
135
+ #
136
+ # @step_input field_path [String] The field to test, prepended with "events.0"
137
+ # @step_input platform_values [DataTable] A table of acceptable values for each platform
138
+ Then('the event {string} equals the platform-dependent boolean:') do |field_path, platform_values|
139
+ test_boolean_platform_values('error', "events.0.#{field_path}", platform_values)
140
+ end
141
+
142
+ # See `the payload field {string} equals the platform-dependent string:`
143
+ #
144
+ # @step_input field_path [String] The field to test, prepended with "events.0.exceptions.0."
145
+ # @step_input platform_values [DataTable] A table of acceptable values for each platform
146
+ Then('the exception {string} equals the platform-dependent string:') do |field_path, platform_values|
147
+ test_string_platform_values('error', "events.0.exceptions.0.#{field_path}", platform_values)
148
+ end
149
+
150
+ # See `the payload field {string} equals the platform-dependent string:`
151
+ #
152
+ # @step_input field_path [String] The field to test, prepended with "events.0.exceptions.0.stacktrace.#!{num}"
153
+ # @step_input num [Integer] The index of the stack frame to test
154
+ # @step_input platform_values [DataTable] A table of acceptable values for each platform
155
+ Then('the {string} of stack frame {int} equals the platform-dependent string:') do |field_path, num, platform_values|
156
+ test_string_platform_values('error', "events.0.exceptions.0.stacktrace.#{num}.#{field_path}", platform_values)
157
+ end
158
+
159
+ # Sends keys to a given element, clearing it first
160
+ # Requires a running Appium driver
161
+ #
162
+ # @step_input keys [String] The keys to send to the element
163
+ # @step_input element_id [String] The locator id
164
+ When('I clear and send the keys {string} to the element {string}') do |keys, element_id|
165
+ Maze.driver.clear_and_send_keys_to_element(element_id, keys)
166
+ end
167
+
168
+ def get_expected_platform_value(platform_values)
169
+ os = Maze::Helper.get_current_platform
170
+ expected_value = Hash[platform_values.raw][os.downcase]
171
+ raise("There is no expected value for the current platform \"#{os}\"") if expected_value.nil?
172
+
173
+ expected_value
174
+ end
175
+
176
+ def should_skip_platform_check(expected_value)
177
+ expected_value.eql?('@skip')
178
+ end
179
+
180
+ def test_string_platform_values(request_type, field_path, platform_values)
181
+ expected_value = get_expected_platform_value(platform_values)
182
+ return if should_skip_platform_check(expected_value)
183
+
184
+ list = Maze::Server.list_for(request_type)
185
+ payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
186
+ assert_equal_with_nullability(expected_value, payload_value)
187
+ end
188
+
189
+ def test_boolean_platform_values(request_type, field_path, platform_values)
190
+ expected_value = get_expected_platform_value(platform_values)
191
+ return if should_skip_platform_check(expected_value)
192
+
193
+ expected_bool = case expected_value.downcase
194
+ when 'true'
195
+ true
196
+ when 'false'
197
+ false
198
+ else
199
+ expected_value
200
+ end
201
+ list = Maze::Server.list_for(request_type)
202
+ payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
203
+ assert_equal_with_nullability(expected_bool, payload_value)
204
+ end
205
+
206
+ def test_numeric_platform_values(request_type, field_path, platform_values)
207
+ expected_value = get_expected_platform_value(platform_values)
208
+ return if should_skip_platform_check(expected_value)
209
+
210
+ list = Maze::Server.list_for(request_type)
211
+ payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
212
+
213
+ # Need to do a little more processing here to allow floats
214
+ special_value = expected_value.eql?('@null') || expected_value.eql?('@not_null')
215
+ expectation = special_value ? expected_value : expected_value.to_f
216
+ assert_equal_with_nullability(expectation, payload_value)
217
+ end
218
+
219
+ def assert_equal_with_nullability(expected_value, payload_value)
220
+ case expected_value
221
+ when '@null'
222
+ Maze.check.nil(payload_value)
223
+ when '@not_null'
224
+ Maze.check.not_nil(payload_value)
225
+ else
226
+ Maze.check.equal(expected_value, payload_value)
227
+ end
228
+ end