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.
- checksums.yaml +7 -0
- data/bin/bugsnag-print-load-paths +6 -0
- data/bin/download-logs +76 -0
- data/bin/maze-runner +136 -0
- data/bin/upload-app +56 -0
- data/lib/features/scripts/await-android-emulator.sh +11 -0
- data/lib/features/scripts/clear-android-app-data.sh +8 -0
- data/lib/features/scripts/force-stop-android-app.sh +8 -0
- data/lib/features/scripts/install-android-app.sh +15 -0
- data/lib/features/scripts/launch-android-app.sh +38 -0
- data/lib/features/scripts/launch-android-emulator.sh +15 -0
- data/lib/features/steps/android_steps.rb +51 -0
- data/lib/features/steps/app_automator_steps.rb +228 -0
- data/lib/features/steps/aws_sam_steps.rb +212 -0
- data/lib/features/steps/breadcrumb_steps.rb +50 -0
- data/lib/features/steps/browser_steps.rb +93 -0
- data/lib/features/steps/build_api_steps.rb +25 -0
- data/lib/features/steps/document_server_steps.rb +7 -0
- data/lib/features/steps/error_reporting_steps.rb +342 -0
- data/lib/features/steps/feature_flag_steps.rb +190 -0
- data/lib/features/steps/header_steps.rb +72 -0
- data/lib/features/steps/log_steps.rb +29 -0
- data/lib/features/steps/multipart_request_steps.rb +142 -0
- data/lib/features/steps/network_steps.rb +75 -0
- data/lib/features/steps/payload_steps.rb +234 -0
- data/lib/features/steps/proxy_steps.rb +34 -0
- data/lib/features/steps/query_parameter_steps.rb +31 -0
- data/lib/features/steps/request_assertion_steps.rb +107 -0
- data/lib/features/steps/runner_steps.rb +406 -0
- data/lib/features/steps/session_tracking_steps.rb +116 -0
- data/lib/features/steps/value_steps.rb +119 -0
- data/lib/features/support/env.rb +7 -0
- data/lib/features/support/internal_hooks.rb +260 -0
- data/lib/maze/appium_server.rb +112 -0
- data/lib/maze/assertions/request_set_assertions.rb +97 -0
- data/lib/maze/aws/sam.rb +112 -0
- data/lib/maze/bitbar_devices.rb +84 -0
- data/lib/maze/bitbar_utils.rb +112 -0
- data/lib/maze/browser_stack_devices.rb +160 -0
- data/lib/maze/browser_stack_utils.rb +164 -0
- data/lib/maze/browsers_bs.yml +220 -0
- data/lib/maze/browsers_cbt.yml +100 -0
- data/lib/maze/bugsnag_config.rb +42 -0
- data/lib/maze/capabilities.rb +126 -0
- data/lib/maze/checks/assert_check.rb +91 -0
- data/lib/maze/checks/noop_check.rb +34 -0
- data/lib/maze/compare.rb +161 -0
- data/lib/maze/configuration.rb +174 -0
- data/lib/maze/docker.rb +108 -0
- data/lib/maze/document_server.rb +46 -0
- data/lib/maze/driver/appium.rb +217 -0
- data/lib/maze/driver/browser.rb +138 -0
- data/lib/maze/driver/resilient_appium.rb +51 -0
- data/lib/maze/errors.rb +20 -0
- data/lib/maze/helper.rb +118 -0
- data/lib/maze/hooks/appium_hooks.rb +216 -0
- data/lib/maze/hooks/browser_hooks.rb +68 -0
- data/lib/maze/hooks/command_hooks.rb +9 -0
- data/lib/maze/hooks/hooks.rb +61 -0
- data/lib/maze/interactive_cli.rb +173 -0
- data/lib/maze/logger.rb +73 -0
- data/lib/maze/macos_utils.rb +14 -0
- data/lib/maze/network.rb +49 -0
- data/lib/maze/option/parser.rb +245 -0
- data/lib/maze/option/processor.rb +143 -0
- data/lib/maze/option/validator.rb +184 -0
- data/lib/maze/option.rb +64 -0
- data/lib/maze/plugins/bugsnag_reporting_plugin.rb +49 -0
- data/lib/maze/plugins/cucumber_report_plugin.rb +101 -0
- data/lib/maze/plugins/global_retry_plugin.rb +38 -0
- data/lib/maze/proxy.rb +114 -0
- data/lib/maze/request_list.rb +82 -0
- data/lib/maze/retry_handler.rb +76 -0
- data/lib/maze/runner.rb +149 -0
- data/lib/maze/sauce_labs_utils.rb +96 -0
- data/lib/maze/server.rb +207 -0
- data/lib/maze/servlets/base_servlet.rb +22 -0
- data/lib/maze/servlets/command_servlet.rb +44 -0
- data/lib/maze/servlets/log_servlet.rb +64 -0
- data/lib/maze/servlets/reflective_servlet.rb +69 -0
- data/lib/maze/servlets/servlet.rb +160 -0
- data/lib/maze/smart_bear_utils.rb +71 -0
- data/lib/maze/store.rb +15 -0
- data/lib/maze/terminating_server.rb +129 -0
- data/lib/maze/timers.rb +51 -0
- data/lib/maze/wait.rb +35 -0
- data/lib/maze.rb +27 -0
- metadata +371 -0
@@ -0,0 +1,406 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require_relative '../../maze/wait'
|
3
|
+
|
4
|
+
# @!group Runner steps
|
5
|
+
|
6
|
+
# Sets an environment variable for subsequent scripts or commands.
|
7
|
+
#
|
8
|
+
# @step_input key [String] The environment variable
|
9
|
+
# @step_input value [String] The intended value of the environment variable
|
10
|
+
When('I set environment variable {string} to {string}') do |key, value|
|
11
|
+
Maze::Runner.environment[key] = value
|
12
|
+
end
|
13
|
+
|
14
|
+
# Sets an environment variable to a given endpoint.
|
15
|
+
#
|
16
|
+
# @step_input endpoint [String] The endpoint to set
|
17
|
+
# @step_input name [String] The environment variable
|
18
|
+
When('I store the {word} endpoint in the environment variable {string}') do |endpoint, name|
|
19
|
+
steps %(
|
20
|
+
When I set environment variable "#{name}" to "http://maze-runner:#{Maze.config.port}/#{endpoint}"
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Sets an environment variable to the currently set API key.
|
25
|
+
#
|
26
|
+
# @step_input name [String] The environment variable
|
27
|
+
When('I store the api key in the environment variable {string}') do |name|
|
28
|
+
steps %Q{
|
29
|
+
When I set environment variable "#{name}" to "#{$api_key}"
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
# Runs a script, blocking until it returns.
|
34
|
+
#
|
35
|
+
# @step_input script_path [String] Path to the script to be run
|
36
|
+
When('I run the script {string} synchronously') do |script_path|
|
37
|
+
Maze::Runner.run_script(script_path, blocking: true)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Runs a script with a given interpreter, blocking until it returns.
|
41
|
+
#
|
42
|
+
# @step_input script_path [String] Path to the script to be run
|
43
|
+
# @step_input command [String] The command to run the script with, e.g. 'ruby'
|
44
|
+
When('I run the script {string} using {word} synchronously') do |script_path, command|
|
45
|
+
Maze::Runner.run_script(script_path, blocking: true, command: command)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Runs a script.
|
49
|
+
#
|
50
|
+
# @step_input script_path [String] Path to the script to be run
|
51
|
+
When('I run the script {string}') do |script_path|
|
52
|
+
Maze::Runner.run_script script_path
|
53
|
+
end
|
54
|
+
|
55
|
+
# Starts a docker-compose service.
|
56
|
+
#
|
57
|
+
# @step_input service [String] The name of the service to run
|
58
|
+
When('I start the service {string}') do |service|
|
59
|
+
Maze::Docker.start_service service
|
60
|
+
end
|
61
|
+
|
62
|
+
# Runs a docker-compose service using a specific command.
|
63
|
+
#
|
64
|
+
# @step_input service [String] The name of the service to run
|
65
|
+
# @step_input command [String] The command to run inside the service
|
66
|
+
When('I run the service {string} with the command {string}') do |service, command|
|
67
|
+
Maze::Docker.start_service(service, command: command)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Runs a docker-compose service in an interactive CLI.
|
71
|
+
#
|
72
|
+
# @step_input service [String] The name of the service to run
|
73
|
+
When('I run the service {string} interactively') do |service|
|
74
|
+
# Stop the old session if one exists
|
75
|
+
step('I stop the current shell') if Maze::Runner.interactive_session?
|
76
|
+
|
77
|
+
Maze::Docker.start_service(service, interactive: true)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Runs a docker-compose service using a specific command in an interactive CLI.
|
81
|
+
#
|
82
|
+
# @step_input service [String] The name of the service to run
|
83
|
+
# @step_input command [String] The command to run inside the service
|
84
|
+
When('I run the service {string} with the command {string} interactively') do |service, command|
|
85
|
+
# Stop the old session if one exists
|
86
|
+
step('I stop the current shell') if Maze::Runner.interactive_session?
|
87
|
+
|
88
|
+
Maze::Docker.start_service(service, command: command, interactive: true)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Runs a docker-compose service using a specific command provided as a Gherkin multi-line string.
|
92
|
+
#
|
93
|
+
# @step_input service [String] The name of the service to run
|
94
|
+
# @step_input command [String] The command to run inside the service (as a Gherkin multi-line string)
|
95
|
+
When('I run the service {string} with the command') do |service, command|
|
96
|
+
one_line_cmd = command.gsub("\n", ' ').gsub(/ +/, ' ')
|
97
|
+
Maze::Docker.start_service(service, command: one_line_cmd)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Allows validation of the last exit code of the last run docker-compose command.
|
101
|
+
# Will fail if no commands have been run.
|
102
|
+
#
|
103
|
+
# @step_input expected_code [Integer] The expected exit code
|
104
|
+
Then('the exit code of the last docker command was {int}') do |expected_code|
|
105
|
+
wait = Maze::Wait.new(timeout: Maze.config.receive_requests_wait)
|
106
|
+
success = wait.until { !Maze::Docker.last_exit_code.nil? }
|
107
|
+
|
108
|
+
Maze.check.true(success, 'No docker exit code available to verify')
|
109
|
+
Maze.check.equal(Maze::Docker.last_exit_code, expected_code)
|
110
|
+
end
|
111
|
+
|
112
|
+
# A shortcut for the above assuming 0 as a successful exit code
|
113
|
+
# Will fail if no commands have been run
|
114
|
+
Then('the last run docker command exited successfully') do
|
115
|
+
step('the exit code of the last docker command was 0')
|
116
|
+
end
|
117
|
+
|
118
|
+
# Allows testing that the last exit code was not 0
|
119
|
+
# Will fail if no commands have been run
|
120
|
+
Then('the last run docker command did not exit successfully') do
|
121
|
+
wait = Maze::Wait.new(timeout: Maze.config.receive_requests_wait)
|
122
|
+
success = wait.until { !Maze::Docker.last_exit_code.nil? }
|
123
|
+
|
124
|
+
Maze.check.true(success, 'No docker exit code available to verify')
|
125
|
+
Maze.check.not_equal(Maze::Docker.last_exit_code, 0)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Allows testing a docker command output a specific string
|
129
|
+
# Will fail if no commands have been run
|
130
|
+
#
|
131
|
+
# @step_input expected_string [String] The string expected in a single log line
|
132
|
+
Then('the last run docker command output {string}') do |expected_string|
|
133
|
+
wait = Maze::Wait.new(timeout: Maze.config.receive_requests_wait)
|
134
|
+
success = wait.until { !Maze::Docker.last_command_logs.nil? }
|
135
|
+
|
136
|
+
Maze.check.true(success, 'No docker logs available to verify')
|
137
|
+
|
138
|
+
docker_output = Maze::Docker.last_command_logs
|
139
|
+
output_included = docker_output.any? { |line| line.include?(expected_string) }
|
140
|
+
|
141
|
+
Maze.check.true(output_included, %(
|
142
|
+
No line of output included '#{expected_string}'.
|
143
|
+
Full output:
|
144
|
+
#{docker_output.join('\n')}
|
145
|
+
))
|
146
|
+
end
|
147
|
+
|
148
|
+
# Waits for a number of seconds, performing no actions.
|
149
|
+
#
|
150
|
+
# @step_input seconds [Integer] The number of seconds to sleep for
|
151
|
+
When('I wait for {int} second(s)') do |seconds|
|
152
|
+
$logger.warn 'Sleep was used! Please avoid using sleep in tests!'
|
153
|
+
sleep(seconds)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Starts an interactive shell
|
157
|
+
When('I start a new shell') do
|
158
|
+
# Stop the old session if one exists
|
159
|
+
step('I stop the current shell') if Maze::Runner.interactive_session?
|
160
|
+
|
161
|
+
Maze::Runner.start_interactive_session
|
162
|
+
end
|
163
|
+
|
164
|
+
# Stops currently running interactive shell
|
165
|
+
When('I stop the current shell') do
|
166
|
+
shell = Maze::Runner.interactive_session
|
167
|
+
result = Maze::Runner.stop_interactive_session
|
168
|
+
|
169
|
+
Maze.check.true(result, 'The shell is still running when it should have exited')
|
170
|
+
Maze.check.false(shell.running?, 'The shell is still running when it should have exited')
|
171
|
+
end
|
172
|
+
|
173
|
+
# Run a command on the shell
|
174
|
+
#
|
175
|
+
# @step_input command [String] The command to run on the shell
|
176
|
+
When('I input {string} interactively') do |command|
|
177
|
+
current_shell = Maze::Runner.interactive_session
|
178
|
+
success = current_shell.run_command(command)
|
179
|
+
Maze.check.true(success, 'The terminal had already closed')
|
180
|
+
end
|
181
|
+
|
182
|
+
# Send a return or enter to the interactive session
|
183
|
+
When('I input a return interactively') do
|
184
|
+
step('I input "" interactively')
|
185
|
+
end
|
186
|
+
|
187
|
+
# Assert the current stdout line in the shell exactly matches the given string
|
188
|
+
#
|
189
|
+
# @step_input expected [String] The expected string
|
190
|
+
Then('the current stdout line is {string}') do |expected|
|
191
|
+
current_shell = Maze::Runner.interactive_session
|
192
|
+
Maze.check.equal(expected, current_shell.current_buffer)
|
193
|
+
end
|
194
|
+
|
195
|
+
# Assert the current stdout line in the shell includes the given string
|
196
|
+
#
|
197
|
+
# @step_input expected [String] The expected string
|
198
|
+
Then('the current stdout line contains {string}') do |expected|
|
199
|
+
current_shell = Maze::Runner.interactive_session
|
200
|
+
Maze.check.include(current_shell.current_buffer, expected)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Waits for a line matching a regex to be present in the current stdout
|
204
|
+
# Times out after Maze.config.receive_requests_wait seconds.
|
205
|
+
#
|
206
|
+
# @step_input regex [String] The regex to match against
|
207
|
+
Then('I wait for the current stdout line to match the regex {string}') do |regex|
|
208
|
+
wait = Maze::Wait.new(timeout: Maze.config.receive_requests_wait)
|
209
|
+
shell = Maze::Runner.interactive_session
|
210
|
+
|
211
|
+
success = wait.until { shell.current_buffer.match?(regex) }
|
212
|
+
|
213
|
+
Maze.check.true(success, "The current output line \"#{shell.current_buffer}\" did not match \"#{regex}\"")
|
214
|
+
end
|
215
|
+
|
216
|
+
# Waits for a specific shell prompt to be present in the buffered stdout line,
|
217
|
+
# timing out after Maze.config.receive_requests_wait seconds.
|
218
|
+
#
|
219
|
+
# @step_input expected_prompt [String] The prompt expected in the current buffer
|
220
|
+
Then('I wait for the shell prompt {string}') do |expected_prompt|
|
221
|
+
wait = Maze::Wait.new(timeout: Maze.config.receive_requests_wait)
|
222
|
+
shell = Maze::Runner.interactive_session
|
223
|
+
|
224
|
+
success = wait.until { shell.current_buffer == expected_prompt }
|
225
|
+
|
226
|
+
Maze.check.true(success, "The current output line \"#{shell.current_buffer}\" did not match \"#{expected_prompt}\"")
|
227
|
+
end
|
228
|
+
|
229
|
+
# Verify a string appears in the stdout logs
|
230
|
+
#
|
231
|
+
# @step_input expected_line [String] The string present in stdout logs
|
232
|
+
Then('the shell has output {string} to stdout') do |expected_line|
|
233
|
+
current_shell = Maze::Runner.interactive_session
|
234
|
+
match = current_shell.stdout_lines.any? { |line| line == expected_line }
|
235
|
+
Maze.check.true(match, "No output lines from #{current_shell.stdout_lines} matched #{expected_line}")
|
236
|
+
end
|
237
|
+
|
238
|
+
# Wait for a string to appear in the stdout logs, timing out after Maze.config.receive_requests_wait seconds.
|
239
|
+
#
|
240
|
+
# @step_input expected_line [String] The string present in stdout logs
|
241
|
+
Then('I wait for the shell to output {string} to stdout') do |expected_line|
|
242
|
+
wait = Maze::Wait.new(timeout: Maze.config.receive_requests_wait)
|
243
|
+
current_shell = Maze::Runner.interactive_session
|
244
|
+
|
245
|
+
success = wait.until do
|
246
|
+
current_shell.stdout_lines.any? { |line| line == expected_line }
|
247
|
+
end
|
248
|
+
|
249
|
+
Maze.check.true(success, "No output lines from #{current_shell.stdout_lines} matched #{expected_line}")
|
250
|
+
end
|
251
|
+
|
252
|
+
# Verify a string using a regex in the stdout logs
|
253
|
+
#
|
254
|
+
# @step_input regex_matcher [String] The regex expected to match a line in stdout logs
|
255
|
+
Then('the shell has output a match for the regex {string} to stdout') do |regex_matcher|
|
256
|
+
current_shell = Maze::Runner.interactive_session
|
257
|
+
match = current_shell.stdout_lines.any? { |line| line.match?(regex_matcher) }
|
258
|
+
Maze.check.true(match, "No output lines from #{current_shell.stdout_lines} matched #{regex_matcher}")
|
259
|
+
end
|
260
|
+
|
261
|
+
# Wait for a string matching a regex in the stdout logs, timing out after Maze.config.receive_requests_wait seconds.
|
262
|
+
#
|
263
|
+
# @step_input regex_matcher [String] The regex expected to match a line in stdout logs
|
264
|
+
Then('I wait for the shell to output a match for the regex {string} to stdout') do |regex_matcher|
|
265
|
+
wait = Maze::Wait.new(timeout: Maze.config.receive_requests_wait)
|
266
|
+
current_shell = Maze::Runner.interactive_session
|
267
|
+
|
268
|
+
success = wait.until do
|
269
|
+
current_shell.stdout_lines.any? { |line| line.match?(regex_matcher) }
|
270
|
+
end
|
271
|
+
|
272
|
+
Maze.check.true(success, "No output lines from #{current_shell.stdout_lines} matched #{regex_matcher}")
|
273
|
+
end
|
274
|
+
|
275
|
+
# Wait for the shell to output a number of strings in STDOUT, as defined by a table.
|
276
|
+
# This step will time out after Maze.config.receive_requests_wait seconds.
|
277
|
+
#
|
278
|
+
# @step_input expected_lines [Array] An array of strings expected in STDOUT
|
279
|
+
Then('I wait for the interactive shell to output the following lines in stdout') do |expected_lines|
|
280
|
+
wait = Maze::Wait.new(timeout: Maze.config.receive_requests_wait)
|
281
|
+
current_shell = Maze::Runner.interactive_session
|
282
|
+
|
283
|
+
success = wait.until do
|
284
|
+
current_stdout = current_shell.stdout_lines.join("\n")
|
285
|
+
current_stdout.include?(expected_lines)
|
286
|
+
end
|
287
|
+
|
288
|
+
Maze.check.true(
|
289
|
+
success,
|
290
|
+
"Lines present in stdout: #{current_shell.stdout_lines} did not include all of: #{expected_lines}"
|
291
|
+
)
|
292
|
+
end
|
293
|
+
|
294
|
+
# Verify a string appears in the stderr logs
|
295
|
+
#
|
296
|
+
# @step_input expected_err [String] The string present in stderr logs
|
297
|
+
Then('the shell has output {string} to stderr') do |expected_err|
|
298
|
+
current_shell = Maze::Runner.interactive_session
|
299
|
+
match = current_shell.stderr_lines.any? { |line| line == expected_err }
|
300
|
+
Maze.check.true(match, "No output lines from #{current_shell.stderr_lines} matched #{expected_err}")
|
301
|
+
end
|
302
|
+
|
303
|
+
# Wait for a string to appear in the stderr logs
|
304
|
+
#
|
305
|
+
# @step_input expected_line [String] The string present in stderr logs
|
306
|
+
Then('I wait for the shell to output {string} to stderr') do |expected_line|
|
307
|
+
wait = Maze::Wait.new(timeout: Maze.config.receive_requests_wait)
|
308
|
+
current_shell = Maze::Runner.interactive_session
|
309
|
+
|
310
|
+
success = wait.until do
|
311
|
+
current_shell.stderr_lines.any? { |line| line == expected_line }
|
312
|
+
end
|
313
|
+
|
314
|
+
Maze.check.true(success, "No output lines from #{current_shell.stderr_lines} matched #{expected_line}")
|
315
|
+
end
|
316
|
+
|
317
|
+
# Verify the last interactive command exited successfully (assuming a 0 is a success)
|
318
|
+
Then('the last interactive command exited successfully') do
|
319
|
+
Maze.check.true(
|
320
|
+
Maze::Runner.interactive_session?,
|
321
|
+
'No interactive session is running so the exit code cannot be checked'
|
322
|
+
)
|
323
|
+
|
324
|
+
uuid = SecureRandom.uuid
|
325
|
+
|
326
|
+
steps %Q{
|
327
|
+
When I input "[ $? = 0 ] && echo '#{uuid} exited with 0' || echo '#{uuid} exited with error'" interactively
|
328
|
+
Then I wait for the shell to output a match for the regex "#{uuid} exited with 0" to stdout
|
329
|
+
}
|
330
|
+
end
|
331
|
+
|
332
|
+
# Verify the exit code of the last interactive command
|
333
|
+
#
|
334
|
+
# @step_input exit_code [Integer] The expected exit code
|
335
|
+
Then('the last interactive command exit code is {int}') do |exit_code|
|
336
|
+
Maze.check.true(
|
337
|
+
Maze::Runner.interactive_session?,
|
338
|
+
'No interactive session is running so the exit code cannot be checked'
|
339
|
+
)
|
340
|
+
|
341
|
+
uuid = SecureRandom.uuid
|
342
|
+
|
343
|
+
steps %Q{
|
344
|
+
When I input "echo #{uuid} $?" interactively
|
345
|
+
Then I wait for the shell to output a match for the regex "#{uuid} #{exit_code}" to stdout
|
346
|
+
}
|
347
|
+
end
|
348
|
+
|
349
|
+
# Assert that the last interactive command exited with an error code (assuming non-0 is an error)
|
350
|
+
Then('the last interactive command exited with an error code') do
|
351
|
+
Maze.check.true(
|
352
|
+
Maze::Runner.interactive_session?,
|
353
|
+
'No interactive session is running so the exit code cannot be checked'
|
354
|
+
)
|
355
|
+
|
356
|
+
uuid = SecureRandom.uuid
|
357
|
+
|
358
|
+
steps %Q{
|
359
|
+
When I input "[ $? = 0 ] && echo '#{uuid} exited with 0' || echo '#{uuid} exited with error'" interactively
|
360
|
+
Then I wait for the shell to output a match for the regex "#{uuid} exited with error" to stdout
|
361
|
+
}
|
362
|
+
end
|
363
|
+
|
364
|
+
# Assert that an expected_line is present in a file located relative to the interactive terminal's CWD
|
365
|
+
#
|
366
|
+
# @step_input filename [String] The file tested, relative to the CWD of the interactive terminal
|
367
|
+
# @step_input expected_line [String] The line expected in the file
|
368
|
+
Then('the interactive file {string} contains {string}') do |filename, expected_line|
|
369
|
+
steps %(
|
370
|
+
When I input "fgrep '#{expected_line.gsub(/"/, '\"')}' #{filename}" interactively
|
371
|
+
And I wait for the current stdout line to match the regex "[#>$]\\s?"
|
372
|
+
Then the last interactive command exited successfully
|
373
|
+
)
|
374
|
+
end
|
375
|
+
|
376
|
+
# Assert that a line is not present in a file located relative to the interactive terminal's CWD
|
377
|
+
#
|
378
|
+
# @step_input filename [String] The file tested, relative to the CWD of the interactive terminal
|
379
|
+
# @step_input excluded_line [String] The line that should not be present be in the file
|
380
|
+
Then('the interactive file {string} does not contain {string}') do |filename, excluded_line|
|
381
|
+
steps %(
|
382
|
+
When I input "fgrep '#{excluded_line.gsub(/"/, '\"')}' #{filename}" interactively
|
383
|
+
And I wait for the current stdout line to match the regex "[#>$]\\s?"
|
384
|
+
Then the last interactive command exited with an error code
|
385
|
+
)
|
386
|
+
end
|
387
|
+
|
388
|
+
# Assert that a file located relative to the CWD of the interactive terminal contains all of the expected lines
|
389
|
+
#
|
390
|
+
# @step_input filename [String] The file tested, relative to the CWD of the interactive terminal
|
391
|
+
# @step_input expected_lines [String] The lines expected in the file as a multi-line string
|
392
|
+
Then('the interactive file {string} contains:') do |filename, expected_lines|
|
393
|
+
expected_lines.each_line do |line|
|
394
|
+
step("the interactive file '#{filename}' contains '#{line.chomp}'")
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
# Assert that a file located relative to the CWD of the interactive terminal does not contain any of the excluded lines
|
399
|
+
#
|
400
|
+
# @step_input filename [String] The file tested, relative to the CWD of the interactive terminal
|
401
|
+
# @step_input excluded_lines [String] The lines that should not be present in the file, as a multi-line string
|
402
|
+
Then('the interactive file {string} does not contain:') do |filename, excluded_lines|
|
403
|
+
excluded_lines.each_line do |line|
|
404
|
+
step("the interactive file '#{filename}' does not contain '#{line.chomp}'")
|
405
|
+
end
|
406
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# @!group Session tracking steps
|
2
|
+
|
3
|
+
# Verifies that generic elements of a session payload are present.
|
4
|
+
# APIKey fields and headers are tested against the '$api_key' global variable.
|
5
|
+
#
|
6
|
+
# @step_input payload_version [String] The payload version expected
|
7
|
+
# @step_input notifier_name [String] The expected name of the notifier
|
8
|
+
Then('the session is valid for the session reporting API version {string} for the {string} notifier') \
|
9
|
+
do |payload_version, notifier_name|
|
10
|
+
steps %(
|
11
|
+
Then the session "bugsnag-api-key" header equals "#{$api_key}"
|
12
|
+
And the session "bugsnag-payload-version" header equals "#{payload_version}"
|
13
|
+
And the session "Content-Type" header equals "application/json"
|
14
|
+
And the session "Bugsnag-Sent-At" header is a timestamp
|
15
|
+
|
16
|
+
And the session payload field "notifier.name" equals "#{notifier_name}"
|
17
|
+
And the session payload field "notifier.url" is not null
|
18
|
+
And the session payload field "notifier.version" is not null
|
19
|
+
|
20
|
+
And the session payload field "app" is not null
|
21
|
+
And the session payload field "device" is not null
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Verifies that generic elements of a session payload are present for the React Native notifier
|
26
|
+
# APIKey fields and headers are tested against the '$api_key' global variable.
|
27
|
+
#
|
28
|
+
# @step_input payload_version [String] The payload version expected
|
29
|
+
# @step_input notifier_name [String] The expected name of the notifier
|
30
|
+
# TODO: I'm reluctant to risk changing the previous step implementation right now, but we should consider
|
31
|
+
# refactoring the two at some point to avoid duplication.
|
32
|
+
Then('the session is valid for the session reporting API version {string} for the React Native notifier') do |payload_version|
|
33
|
+
steps %{
|
34
|
+
Then the session "bugsnag-api-key" header equals "#{$api_key}"
|
35
|
+
And the session "bugsnag-payload-version" header equals "#{payload_version}"
|
36
|
+
And the session "Content-Type" header equals "application/json"
|
37
|
+
And the session "Bugsnag-Sent-At" header is a timestamp
|
38
|
+
|
39
|
+
And the session payload field "notifier.name" matches the regex "(Android|iOS) Bugsnag Notifier"
|
40
|
+
And the session payload field "notifier.url" is not null
|
41
|
+
And the session payload field "notifier.version" is not null
|
42
|
+
|
43
|
+
And the session payload field "app" is not null
|
44
|
+
And the session payload field "device" is not null
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Tests whether a value in the first session entry matches a literal.
|
49
|
+
#
|
50
|
+
# @step_input field [String] The relative location of the value to test
|
51
|
+
# @step_input literal [Enum] The literal to test against, one of: true, false, null, not null
|
52
|
+
Then(/^the session "(.+)" is (true|false|null|not null)$/) do |field, literal|
|
53
|
+
step "the session payload field \"sessions.0.#{field}\" is #{literal}"
|
54
|
+
end
|
55
|
+
|
56
|
+
# Tests whether a value in the first session entry matches a string.
|
57
|
+
#
|
58
|
+
# @step_input field [String] The relative location of the value to test
|
59
|
+
# @step_input string_value [String] The string to match against
|
60
|
+
Then('the session {string} equals {string}') do |field, string_value|
|
61
|
+
step "the session payload field \"sessions.0.#{field}\" equals \"#{string_value}\""
|
62
|
+
end
|
63
|
+
|
64
|
+
# Tests whether a value in the first session entry is a timestamp.
|
65
|
+
#
|
66
|
+
# @step_input field [String] The relative location of the value to test
|
67
|
+
Then('the session {string} is a timestamp') do |field|
|
68
|
+
step "the session payload field \"sessions.0.#{field}\" matches the regex \"#{TIMESTAMP_REGEX}\""
|
69
|
+
end
|
70
|
+
|
71
|
+
# Tests whether a value in the first sessionCount entry matches a literal.
|
72
|
+
#
|
73
|
+
# @step_input field [String] The relative location of the value to test
|
74
|
+
# @step_input literal [Enum] The literal to test against, one of: true, false, null, not null
|
75
|
+
Then(/^the sessionCount "(.+)" is (true|false|null|not null)$/) do |field, literal|
|
76
|
+
step "the session payload field \"sessionCounts.0.#{field}\" is #{literal}"
|
77
|
+
end
|
78
|
+
|
79
|
+
# Tests whether a value in the first sessionCount entry matches a string.
|
80
|
+
#
|
81
|
+
# @step_input field [String] The relative location of the value to test
|
82
|
+
# @step_input string_value [String] The string to match against
|
83
|
+
Then('the sessionCount {string} equals {string}') do |field, string_value|
|
84
|
+
step "the session payload field \"sessionCounts.0.#{field}\" equals \"#{string_value}\""
|
85
|
+
end
|
86
|
+
|
87
|
+
# Tests whether a value in the first sessionCount entry equals an integer.
|
88
|
+
#
|
89
|
+
# @step_input field [String] The relative location of the value to test
|
90
|
+
# @step_input int_value [Integer] The integer to test against
|
91
|
+
Then('the sessionCount {string} equals {int}') do |field, int_value|
|
92
|
+
step "the session payload field \"sessionCounts.0.#{field}\" equals #{int_value}"
|
93
|
+
end
|
94
|
+
|
95
|
+
# Tests whether a value in the first sessionCount entry is a timestamp.
|
96
|
+
#
|
97
|
+
# @step_input field [String] The relative location of the value to test
|
98
|
+
Then('the sessionCount {string} is a timestamp') do |field|
|
99
|
+
step "the session payload field \"sessionCounts.0.#{field}\" matches the regex \"#{TIMESTAMP_REGEX}\""
|
100
|
+
end
|
101
|
+
|
102
|
+
# Tests that a payload has an appropriately structured session array
|
103
|
+
Then('the session payload has a valid sessions array') do
|
104
|
+
if sessions = Maze::Server.sessions.current[:body]['sessions']
|
105
|
+
steps %(
|
106
|
+
Then the session "id" is not null
|
107
|
+
And the session "startedAt" is a timestamp
|
108
|
+
)
|
109
|
+
else
|
110
|
+
steps %(
|
111
|
+
Then the sessionCount "sessionsStarted" is not null
|
112
|
+
And the sessionCount "startedAt" is a timestamp
|
113
|
+
)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
# @!group Value steps
|
4
|
+
|
5
|
+
# Stores a payload value against a key for cross-request comparisons.
|
6
|
+
#
|
7
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
8
|
+
# @step_input field [String] The payload field to store
|
9
|
+
# @step_input key [String] The key to store the value against
|
10
|
+
Then('the {word} payload field {string} is stored as the value {string}') do |request_type, field, key|
|
11
|
+
list = Maze::Server.list_for request_type
|
12
|
+
value = Maze::Helper.read_key_path(list.current[:body], field)
|
13
|
+
Maze::Store.values[key] = value.dup
|
14
|
+
end
|
15
|
+
|
16
|
+
# Tests whether a payload field matches a previously stored payload value
|
17
|
+
#
|
18
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
19
|
+
# @step_input field [String] The payload field to test
|
20
|
+
# @step_input key [String] The key indicating a previously stored value
|
21
|
+
Then('the {word} payload field {string} equals the stored value {string}') do |request_type, field, key|
|
22
|
+
list = Maze::Server.list_for request_type
|
23
|
+
payload_value = Maze::Helper.read_key_path(list.current[:body], field)
|
24
|
+
stored_value = Maze::Store.values[key]
|
25
|
+
result = Maze::Compare.value(payload_value, stored_value)
|
26
|
+
Maze.check.true(result.equal?, "Payload value: #{payload_value} does not equal stored value: #{stored_value}")
|
27
|
+
end
|
28
|
+
|
29
|
+
# Tests whether a payload field is distinct from a previously stored payload value
|
30
|
+
#
|
31
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
32
|
+
# @step_input field [String] The payload field to test
|
33
|
+
# @step_input key [String] The key indicating a previously stored value
|
34
|
+
Then('the {word} payload field {string} does not equal the stored value {string}') do |request_type, field, key|
|
35
|
+
list = Maze::Server.list_for request_type
|
36
|
+
payload_value = Maze::Helper.read_key_path(list.current[:body], field)
|
37
|
+
stored_value = Maze::Store.values[key]
|
38
|
+
result = Maze::Compare.value(payload_value, stored_value)
|
39
|
+
Maze.check.false(result.equal?, "Payload value: #{payload_value} equals stored value: #{stored_value}")
|
40
|
+
end
|
41
|
+
|
42
|
+
# Tests whether a payload field matches a previously stored payload value, ignoring case
|
43
|
+
#
|
44
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
45
|
+
# @step_input field [String] The payload field to test
|
46
|
+
# @step_input key [String] The key indicating a previously stored value
|
47
|
+
Then('the {word} payload field {string} equals the stored value {string} ignoring case') do |request_type, field, key|
|
48
|
+
list = Maze::Server.list_for request_type
|
49
|
+
payload_value = Maze::Helper.read_key_path(list.current[:body], field)
|
50
|
+
stored_value = Maze::Store.values[key]
|
51
|
+
payload_value.downcase!
|
52
|
+
stored_value.downcase!
|
53
|
+
result = Maze::Compare.value(payload_value, stored_value)
|
54
|
+
Maze.check.true(result.equal?, "Payload value: #{payload_value} does not equal stored value: #{stored_value}")
|
55
|
+
end
|
56
|
+
|
57
|
+
# Tests whether a payload field is distinct from a previously stored payload value, ignoring case
|
58
|
+
#
|
59
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
60
|
+
# @step_input field [String] The payload field to test
|
61
|
+
# @step_input key [String] The key indicating a previously stored value
|
62
|
+
Then('the {word} payload field {string} does not equal the stored value {string} ignoring case') do |request_type, field, key|
|
63
|
+
list = Maze::Server.list_for request_type
|
64
|
+
payload_value = Maze::Helper.read_key_path(list.current[:body], field)
|
65
|
+
stored_value = Maze::Store.values[key]
|
66
|
+
payload_value.downcase!
|
67
|
+
stored_value.downcase!
|
68
|
+
result = Maze::Compare.value(payload_value, stored_value)
|
69
|
+
Maze.check.false(result.equal?, "Payload value: #{payload_value} equals stored value: #{stored_value}")
|
70
|
+
end
|
71
|
+
|
72
|
+
# Tests whether a payload field is a number (Numeric according to Ruby)
|
73
|
+
#
|
74
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
75
|
+
# @step_input field [String] The payload field to test
|
76
|
+
Then('the {word} payload field {string} is a number') do |request_type, field|
|
77
|
+
list = Maze::Server.list_for request_type
|
78
|
+
value = Maze::Helper.read_key_path(list.current[:body], field)
|
79
|
+
Maze.check.kind_of Numeric, value
|
80
|
+
end
|
81
|
+
|
82
|
+
# Tests whether a payload field is an integer (Integer according to Ruby)
|
83
|
+
#
|
84
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
85
|
+
# @step_input field [String] The payload field to test
|
86
|
+
Then('the {word} payload field {string} is an integer') do |request_type, field|
|
87
|
+
list = Maze::Server.list_for request_type
|
88
|
+
value = Maze::Helper.read_key_path(list.current[:body], field)
|
89
|
+
Maze.check.kind_of Integer, value
|
90
|
+
end
|
91
|
+
|
92
|
+
# Tests whether a payload field is a date (parseable as a Date, according to Ruby)
|
93
|
+
#
|
94
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
95
|
+
# @step_input field [String] The payload field to test
|
96
|
+
Then('the {word} payload field {string} is a date') do |request_type, field|
|
97
|
+
list = Maze::Server.list_for request_type
|
98
|
+
value = Maze::Helper.read_key_path(list.current[:body], field)
|
99
|
+
date = begin
|
100
|
+
Date.parse(value)
|
101
|
+
rescue StandardError
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
Maze.check.kind_of Date, date
|
105
|
+
end
|
106
|
+
|
107
|
+
# Tests whether a payload field (loosely) matches a UUID regex (/[a-fA-F0-9-]!{36}/)
|
108
|
+
#
|
109
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
110
|
+
# @step_input field [String] The payload field to test
|
111
|
+
Then('the {word} payload field {string} is a UUID') do |request_type, field|
|
112
|
+
list = Maze::Server.list_for request_type
|
113
|
+
value = Maze::Helper.read_key_path(list.current[:body], field)
|
114
|
+
Maze.check.not_nil(value, "Expected UUID, got nil for #{field}")
|
115
|
+
match = /[a-fA-F0-9-]{36}/.match(value).size > 0
|
116
|
+
Maze.check.true(match, "Field #{field} is not a UUID, received #{value}")
|
117
|
+
end
|
118
|
+
|
119
|
+
# @!endgroup
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
# The apikey that should be used on this test run
|
4
|
+
$api_key = SecureRandom.hex(16).tr('+/=', 'xyz')
|
5
|
+
|
6
|
+
# A regex providing the pattern expected from timestamps
|
7
|
+
TIMESTAMP_REGEX = /^\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:[\d\.]+(Z|[+-]\d{2}:\d{2})?$/
|