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
@@ -0,0 +1,212 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../maze'
4
+ require_relative '../../maze/aws/sam'
5
+
6
+ # @!group AWS SAM steps
7
+
8
+ # Invoke a lambda directly with 'sam invoke'
9
+ #
10
+ # @step_input lambda_name [String] The name of the lambda to invoke
11
+ # @step_input directory [String] The directory to invoke the lambda in
12
+ Given('I invoke the {string} lambda in {string}') do |lambda_name, directory|
13
+ Maze::Aws::Sam.invoke(directory, lambda_name)
14
+ end
15
+
16
+ # Invoke a lambda directly with 'sam invoke' and the given event
17
+ #
18
+ # @step_input lambda_name [String] The name of the lambda to invoke
19
+ # @step_input directory [String] The directory to invoke the lambda in
20
+ # @step_input event_file [String] The event file to call the lambda with
21
+ Given('I invoke the {string} lambda in {string} with the {string} event') do |lambda_name, directory, event_file|
22
+ Maze::Aws::Sam.invoke(directory, lambda_name, event_file)
23
+ end
24
+
25
+ # Test the exit code of the SAM CLI process.
26
+ #
27
+ # @step_input expected [Integer] The expected exit code
28
+ Then('the SAM exit code equals {int}') do |expected|
29
+ Maze.check.equal(expected, Maze::Aws::Sam.last_exit_code)
30
+ end
31
+
32
+ # Test the Lambda response is empty but not-null. This indicates the Lambda did
33
+ # not respond but did run successfully
34
+ Then('the lambda response is empty') do
35
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
36
+
37
+ Maze.check.equal({}, Maze::Aws::Sam.last_response)
38
+ end
39
+
40
+ # Test a Lambda response field equals the given string.
41
+ #
42
+ # @step_input key_path [String] The response element to test
43
+ # @step_input expected [String] The string to test against
44
+ Then('the lambda response {string} equals {string}') do |key_path, expected|
45
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
46
+
47
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
48
+
49
+ Maze.check.equal(expected, actual)
50
+ end
51
+
52
+ # Test a Lambda response field contains the given string.
53
+ #
54
+ # @step_input key_path [String] The response element to test
55
+ # @step_input expected [String] The string to test against
56
+ Then('the lambda response {string} contains {string}') do |key_path, expected|
57
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
58
+
59
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
60
+
61
+ Maze.check.include(actual, expected)
62
+ end
63
+
64
+ # Test a Lambda response field equals the given integer.
65
+ #
66
+ # @step_input key_path [String] The response element to test
67
+ # @step_input expected [Integer] The integer to test against
68
+ Then('the lambda response {string} equals {int}') do |key_path, expected|
69
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
70
+
71
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
72
+
73
+ Maze.check.equal(expected, actual)
74
+ end
75
+
76
+ # Test a Lambda response field is true.
77
+ #
78
+ # @step_input key_path [String] The response element to test
79
+ Then('the lambda response {string} is true') do |key_path|
80
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
81
+
82
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
83
+
84
+ Maze.check.true(actual)
85
+ end
86
+
87
+ # Test a Lambda response field is false.
88
+ #
89
+ # @step_input key_path [String] The response element to test
90
+ Then('the lambda response {string} is false') do |key_path|
91
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
92
+
93
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
94
+
95
+ Maze.check.false(actual)
96
+ end
97
+
98
+ # Test a Lambda response field is null.
99
+ #
100
+ # @step_input key_path [String] The response element to test
101
+ Then('the lambda response {string} is null') do |key_path|
102
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
103
+
104
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
105
+
106
+ Maze.check.nil(actual)
107
+ end
108
+
109
+ # Test a Lambda response field is not null.
110
+ #
111
+ # @step_input key_path [String] The response element to test
112
+ Then('the lambda response {string} is not null') do |key_path|
113
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
114
+
115
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
116
+
117
+ Maze.check.not_nil(actual)
118
+ end
119
+
120
+ # Test a Lambda response field is greater than the given integer.
121
+ #
122
+ # @step_input key_path [String] The response element to test
123
+ # @step_input expected [Integer] The integer to test against
124
+ Then('the lambda response {string} is greater than {int}') do |key_path, expected|
125
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
126
+
127
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
128
+
129
+ Maze.check.operator(actual, :>, expected)
130
+ end
131
+
132
+ # Test a Lambda response field is less than the given integer.
133
+ #
134
+ # @step_input key_path [String] The response element to test
135
+ # @step_input expected [Integer] The integer to test against
136
+ Then('the lambda response {string} is less than {int}') do |key_path, expected|
137
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
138
+
139
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
140
+
141
+ Maze.check.operator(actual, :<, expected)
142
+ end
143
+
144
+ # Test a Lambda response field starts with the given string.
145
+ #
146
+ # @step_input key_path [String] The response element to test
147
+ # @step_input expected [String] The string to test against
148
+ Then('the lambda response {string} starts with {string}') do |key_path, expected|
149
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
150
+
151
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
152
+
153
+ Maze.check.kind_of(String, actual)
154
+ Maze.check.true(
155
+ actual.start_with?(expected),
156
+ "Field '#{key_path}' value ('#{actual}') does not start with '#{expected}'"
157
+ )
158
+ end
159
+
160
+ # Test a Lambda response field ends with the given string.
161
+ #
162
+ # @step_input key_path [String] The response element to test
163
+ # @step_input expected [String] The string to test against
164
+ Then('the lambda response {string} ends with {string}') do |key_path, expected|
165
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
166
+
167
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
168
+
169
+ Maze.check.kind_of(String, actual)
170
+ Maze.check.true(
171
+ actual.end_with?(expected),
172
+ "Field '#{key_path}' value ('#{actual}') does not start with '#{expected}'"
173
+ )
174
+ end
175
+
176
+ # Test a Lambda response field is an array with a specific number of elements.
177
+ #
178
+ # @step_input key_path [String] The response element to test
179
+ # @step_input expected [Integer] The expected number of elements
180
+ Then('the lambda response {string} is an array with {int} element(s)') do |key_path, expected|
181
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
182
+
183
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
184
+
185
+ Maze.check.kind_of(Array, actual)
186
+ Maze.check.equal(expected, actual.length)
187
+ end
188
+
189
+ # Test a Lambda response field is an array with at least 1 element.
190
+ #
191
+ # @step_input key_path [String] The response element to test
192
+ Then('the lambda response {string} is a non-empty array') do |key_path|
193
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
194
+
195
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
196
+
197
+ Maze.check.kind_of(Array, actual)
198
+ Maze.check.false(actual.empty?)
199
+ end
200
+
201
+ # Test a Lambda response field matches the given regex.
202
+ #
203
+ # @step_input key_path [String] The response element to test
204
+ # @step_input expected [String] The regex to match against
205
+ Then('the lambda response {string} matches the regex {string}') do |key_path, regex|
206
+ expected = Regexp.new(regex)
207
+ Maze.check.not_nil(Maze::Aws::Sam.last_response, 'No lambda response!')
208
+
209
+ actual = Maze::Helper.read_key_path(Maze::Aws::Sam.last_response, key_path)
210
+
211
+ Maze.check.match(expected, actual)
212
+ end
@@ -0,0 +1,50 @@
1
+ # @!group Breadcrumb steps
2
+
3
+ # Tests whether the first event entry contains a specific breadcrumb with a type and name.
4
+ #
5
+ # @step_input type [String] The expected breadcrumb's type
6
+ # @step_input name [String] The expected breadcrumb's name
7
+ Then('the event has a {string} breadcrumb named {string}') do |type, name|
8
+ value = Maze::Server.errors.current[:body]['events'].first['breadcrumbs']
9
+ found = false
10
+ value.each do |crumb|
11
+ found = true if crumb['type'] == type and crumb['name'] == name
12
+ end
13
+ raise("No breadcrumb matched: #{value}") unless found
14
+ end
15
+
16
+ # Tests whether the first event entry contains a specific breadcrumb with a type and message.
17
+ #
18
+ # @step_input type [String] The expected breadcrumb's type
19
+ # @step_input message [String] The expected breadcrumb's message
20
+ Then('the event has a {string} breadcrumb with message {string}') do |type, message|
21
+ value = Maze::Server.errors.current[:body]['events'].first['breadcrumbs']
22
+ found = false
23
+ value.each do |crumb|
24
+ found = true if crumb['type'] == type && crumb['metaData'] && crumb['metaData']['message'] == message
25
+ end
26
+ raise("No breadcrumb matched: #{value}") unless found
27
+ end
28
+
29
+ # Tests whether the first event entry does not contain a breadcrumb with a specific type.
30
+ # Used for confirming filtering of breadcrumbs
31
+ #
32
+ # @step_input type [String] The type of breadcrumb expected to not be present
33
+ Then('the event does not have a {string} breadcrumb') do |type|
34
+ value = Maze::Server.errors.current[:body]['events'].first['breadcrumbs']
35
+ found = false
36
+ value.each do |crumb|
37
+ found = true if crumb['type'] == type
38
+ end
39
+ raise("Breadcrumb with type: #{type} matched") if found
40
+ end
41
+
42
+ # Tests whether any breadcrumb matches a given JSON fixture. This follows all the usual rules for JSON fixture matching.
43
+ #
44
+ # @step_input json_fixture [String] A path to the JSON fixture to compare against
45
+ Then('the event contains a breadcrumb matching the JSON fixture in {string}') do |json_fixture|
46
+ breadcrumbs = Maze::Helper.read_key_path(Maze::Server.errors.current[:body], 'events.0.breadcrumbs')
47
+ expected = JSON.parse(open(json_fixture, &:read))
48
+ match = breadcrumbs.any? { |breadcrumb| Maze::Compare.value(expected, breadcrumb).equal? }
49
+ Maze.check.true(match, 'No breadcrumbs in the event matched the given breadcrumb')
50
+ end
@@ -0,0 +1,93 @@
1
+ # @!group Browser steps
2
+
3
+ When('I navigate to the URL {string}') do |path|
4
+ begin
5
+ $logger.debug "Navigating to: #{path}"
6
+ Maze.driver.navigate.to path
7
+ rescue => exception
8
+ $logger.error("#{exception.class} occurred during navigation attempt with message: #{exception.message}")
9
+ $logger.error("Restarting driver and retrying navigation to: #{path}")
10
+ Maze.driver.restart_driver
11
+ Maze.driver.navigate.to path
12
+ # If a further error occurs it will get thrown as normal
13
+ end
14
+ end
15
+
16
+ Then(/^the error is a valid browser payload for the error reporting API$/) do
17
+ if !/^ie_(8|9|10)$/.match(Maze.config.browser)
18
+ steps %(
19
+ Then the error "Bugsnag-API-Key" header is not null
20
+ And the error "Content-Type" header equals one of:
21
+ | application/json |
22
+ | application/json; charset=UTF-8 |
23
+ And the error "Bugsnag-Payload-Version" header equals "4"
24
+ And the error "Bugsnag-Sent-At" header is a timestamp
25
+ )
26
+ else
27
+ steps %(
28
+ Then the error "apiKey" query parameter is not null
29
+ And the error "payloadVersion" query parameter equals "4"
30
+ And the error "sentAt" query parameter is a timestamp
31
+ )
32
+ end
33
+ steps %(
34
+ And the error payload field "notifier.name" is not null
35
+ And the error payload field "notifier.url" is not null
36
+ And the error payload field "notifier.version" is not null
37
+ And the error payload field "events" is a non-empty array
38
+
39
+ And each element in error payload field "events" has "severity"
40
+ And each element in error payload field "events" has "severityReason.type"
41
+ And each element in error payload field "events" has "unhandled"
42
+ And each element in error payload field "events" has "exceptions"
43
+
44
+ And the exception "type" equals "browserjs"
45
+ )
46
+ end
47
+
48
+ Then('the session is a valid browser payload for the session tracking API') do
49
+ if !/^ie_(8|9|10)$/.match(Maze.config.browser)
50
+ steps %(
51
+ Then the session "Bugsnag-API-Key" header is not null
52
+ And the session "Content-Type" header equals one of:
53
+ | application/json |
54
+ | application/json; charset=UTF-8 |
55
+ And the session "Bugsnag-Payload-Version" header equals "1"
56
+ And the session "Bugsnag-Sent-At" header is a timestamp
57
+ )
58
+ else
59
+ steps %(
60
+ Then the session "apiKey" query parameter is not null
61
+ And the session "payloadVersion" query parameter equals "1"
62
+ And the session "sentAt" query parameter is a timestamp
63
+ )
64
+ end
65
+ steps %(
66
+ And the session payload field "app" is not null
67
+ And the session payload field "device" is not null
68
+ And the session payload field "notifier.name" is not null
69
+ And the session payload field "notifier.url" is not null
70
+ And the session payload field "notifier.version" is not null
71
+ And the session payload has a valid sessions array
72
+ )
73
+ end
74
+
75
+ Then('the event device ID is valid') do
76
+ if Maze.driver.local_storage?
77
+ step('the event "device.id" matches "^c[a-z0-9]{20,32}$"')
78
+ else
79
+ $logger.info('Local storage is not supported in this browser, assuming device ID is null')
80
+ step('the event "device.id" is null')
81
+ end
82
+ end
83
+
84
+ Then('the event device ID is {string}') do |expected_id|
85
+ if Maze.driver.local_storage?
86
+ step("the event \"device.id\" equals \"#{expected_id}\"")
87
+ else
88
+ $logger.info('Local storage is not supported in this browser, assuming device ID is null')
89
+ step('the event "device.id" is null')
90
+ end
91
+ end
92
+
93
+ # @!endgroup
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @!group Build API Steps
4
+
5
+ # Tests whether the top-most payload is valid for the Bugsnag build API
6
+ # APIKey fields and headers are tested against the '$api_key' global variable
7
+ Then('the build is valid for the Build API') do
8
+ steps %(
9
+ And the build payload field "apiKey" equals "#{$api_key}"
10
+ And the build payload field "appVersion" is not null
11
+ )
12
+ end
13
+
14
+ # Tests whether the top-most payload is valid for the Android mapping API
15
+ # APIKey fields and headers are tested against the '$api_key' global variable
16
+ Then('the build is valid for the Android Mapping API') do
17
+ steps %(
18
+ And the build payload field "apiKey" equals "#{$api_key}"
19
+ And the build payload field "proguard" is not null
20
+ And the build payload field "appId" is not null
21
+ And the build payload field "versionCode" is not null
22
+ And the build payload field "buildUUID" is not null
23
+ And the build payload field "versionName" is not null
24
+ )
25
+ end
@@ -0,0 +1,7 @@
1
+ # @!group Document steps
2
+
3
+ # Starts the document server manually. It will be stopped automatically at the end of each scenario
4
+ # (if started in this way).
5
+ When('I start the document server') do
6
+ Maze::DocumentServer.manual_start
7
+ end