bugsnag-maze-runner 6.27.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.
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