bugsnag-maze-runner 6.27.0 → 7.22.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/download-logs +14 -16
- data/bin/maze-runner +53 -15
- data/bin/upload-app +6 -6
- data/lib/features/steps/breadcrumb_steps.rb +44 -14
- data/lib/features/steps/error_reporting_steps.rb +16 -0
- data/lib/features/steps/network_steps.rb +66 -6
- data/lib/features/steps/payload_steps.rb +23 -0
- data/lib/features/steps/request_assertion_steps.rb +87 -8
- data/lib/features/steps/runner_steps.rb +22 -0
- data/lib/features/steps/session_tracking_steps.rb +1 -1
- data/lib/features/steps/trace_steps.rb +206 -0
- data/lib/features/support/internal_hooks.rb +31 -84
- data/lib/maze/api/appium/file_manager.rb +29 -0
- data/lib/maze/aws_public_ip.rb +53 -0
- data/lib/maze/checks/assert_check.rb +9 -31
- data/lib/maze/client/appium/base_client.rb +131 -0
- data/lib/maze/client/appium/bb_client.rb +102 -0
- data/lib/maze/client/appium/bb_devices.rb +127 -0
- data/lib/maze/client/appium/bs_client.rb +91 -0
- data/lib/maze/client/appium/bs_devices.rb +141 -0
- data/lib/maze/client/appium/bs_legacy_client.rb +31 -0
- data/lib/maze/client/appium/local_client.rb +67 -0
- data/lib/maze/client/appium.rb +23 -0
- data/lib/maze/client/bb_api_client.rb +102 -0
- data/lib/maze/client/bb_client_utils.rb +181 -0
- data/lib/maze/client/bs_client_utils.rb +168 -0
- data/lib/maze/client/selenium/base_client.rb +15 -0
- data/lib/maze/client/selenium/bb_browsers.yml +188 -0
- data/lib/maze/client/selenium/bb_client.rb +38 -0
- data/lib/maze/client/selenium/bs_browsers.yml +257 -0
- data/lib/maze/client/selenium/bs_client.rb +89 -0
- data/lib/maze/client/selenium/local_client.rb +16 -0
- data/lib/maze/client/selenium.rb +16 -0
- data/lib/maze/configuration.rb +18 -10
- data/lib/maze/docker.rb +40 -1
- data/lib/maze/driver/appium.rb +5 -24
- data/lib/maze/driver/browser.rb +12 -26
- data/lib/maze/errors.rb +32 -0
- data/lib/maze/generator.rb +55 -0
- data/lib/maze/helper.rb +7 -3
- data/lib/maze/hooks/appium_hooks.rb +29 -190
- data/lib/maze/hooks/browser_hooks.rb +2 -55
- data/lib/maze/hooks/error_code_hook.rb +49 -0
- data/lib/maze/hooks/hooks.rb +2 -2
- data/lib/maze/http_request.rb +21 -0
- data/lib/maze/logger.rb +16 -3
- data/lib/maze/maze_output.rb +88 -0
- data/lib/maze/option/parser.rb +17 -22
- data/lib/maze/option/processor.rb +21 -34
- data/lib/maze/option/validator.rb +38 -67
- data/lib/maze/option.rb +16 -18
- data/lib/maze/plugins/cucumber_report_plugin.rb +1 -1
- data/lib/maze/plugins/error_code_plugin.rb +21 -0
- data/lib/maze/request_list.rb +10 -5
- data/lib/maze/request_repeater.rb +49 -0
- data/lib/maze/retry_handler.rb +4 -13
- data/lib/maze/schemas/OtelTraceSchema.json +390 -0
- data/lib/maze/schemas/trace_schema.rb +7 -0
- data/lib/maze/schemas/trace_validator.rb +98 -0
- data/lib/maze/server.rb +74 -30
- data/lib/maze/servlets/base_servlet.rb +10 -5
- data/lib/maze/servlets/command_servlet.rb +10 -7
- data/lib/maze/servlets/log_servlet.rb +2 -2
- data/lib/maze/servlets/reflective_servlet.rb +12 -11
- data/lib/maze/servlets/servlet.rb +47 -8
- data/lib/maze/servlets/temp.rb +0 -0
- data/lib/maze/servlets/trace_servlet.rb +13 -0
- data/lib/maze.rb +2 -2
- data/lib/utils/deep_merge.rb +17 -0
- data/lib/utils/selenium_money_patch.rb +17 -0
- metadata +101 -21
- data/lib/maze/bitbar_devices.rb +0 -84
- data/lib/maze/bitbar_utils.rb +0 -112
- data/lib/maze/browser_stack_devices.rb +0 -160
- data/lib/maze/browser_stack_utils.rb +0 -164
- data/lib/maze/browsers_bs.yml +0 -220
- data/lib/maze/browsers_cbt.yml +0 -100
- data/lib/maze/capabilities.rb +0 -126
- data/lib/maze/driver/resilient_appium.rb +0 -51
- data/lib/maze/sauce_labs_utils.rb +0 -96
- data/lib/maze/smart_bear_utils.rb +0 -71
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 25918b6a96c58be96023fec6acae1dca6463db11c722fe9ef612f1faa1137f48
|
4
|
+
data.tar.gz: 68af4db3ee29db253541685361060a0b969371752a22c7c7e7e78bfd51c7dc31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5734aa0594c7286ebe127cb4261b0d029f7241a88c090eea5c52a059459e3f7deed26a3fc14d754155ae8d1000b5001d65b3b903e2d98822ccc6cf7a824573e4
|
7
|
+
data.tar.gz: 91d4e5a297ec91c2f71bc2f023632eab9c328fe70bcd61bf511f8eab688b7e85c4cba8a9d5dc5ccec3017a2240daee180f6c0364db490e71376389f77cc5a45f
|
data/bin/download-logs
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require_relative '../lib/maze'
|
5
|
-
require_relative '../lib/maze/
|
5
|
+
require_relative '../lib/maze/client/bs_client_utils'
|
6
6
|
require_relative '../lib/maze/logger'
|
7
7
|
require 'net/http'
|
8
8
|
require 'json'
|
@@ -44,9 +44,9 @@ class DownloadLogEntry
|
|
44
44
|
end
|
45
45
|
|
46
46
|
|
47
|
-
build_info = Maze::
|
48
|
-
|
49
|
-
|
47
|
+
build_info = Maze::Client::BrowserStackClientUtils.build_info username,
|
48
|
+
access_key,
|
49
|
+
opts[:build_id]
|
50
50
|
|
51
51
|
$logger.info "Getting logs for build: #{opts[:build_id]}"
|
52
52
|
|
@@ -55,20 +55,18 @@ class DownloadLogEntry
|
|
55
55
|
|
56
56
|
log_name = "#{opts[:build_id]}-#{index + 1}"
|
57
57
|
|
58
|
-
Maze::
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
58
|
+
Maze::Client::BrowserStackClientUtils.download_log username,
|
59
|
+
access_key,
|
60
|
+
log_name,
|
61
|
+
session['automation_session']['device_logs_url'],
|
62
|
+
:device
|
63
63
|
|
64
64
|
$logger.info "Downloading Appium Logs for Session: #{index + 1}"
|
65
|
-
Maze::
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
65
|
+
Maze::Client::BrowserStackClientUtils.download_log username,
|
66
|
+
access_key,
|
67
|
+
log_name,
|
68
|
+
session['automation_session']['appium_logs_url'],
|
69
|
+
:appium
|
72
70
|
end
|
73
71
|
end
|
74
72
|
end
|
data/bin/maze-runner
CHANGED
@@ -3,37 +3,60 @@
|
|
3
3
|
|
4
4
|
require 'cucumber/cli/main'
|
5
5
|
|
6
|
+
require_relative '../lib/utils/deep_merge'
|
7
|
+
|
6
8
|
require_relative '../lib/maze'
|
7
9
|
|
8
10
|
require_relative '../lib/maze/appium_server'
|
9
|
-
require_relative '../lib/maze/
|
10
|
-
require_relative '../lib/maze/bitbar_devices'
|
11
|
-
require_relative '../lib/maze/browser_stack_devices'
|
12
|
-
require_relative '../lib/maze/browser_stack_utils'
|
11
|
+
require_relative '../lib/maze/api/appium/file_manager'
|
13
12
|
require_relative '../lib/maze/bugsnag_config'
|
14
|
-
require_relative '../lib/maze/
|
13
|
+
require_relative '../lib/maze/client/bb_api_client'
|
14
|
+
require_relative '../lib/maze/client/bb_client_utils'
|
15
|
+
require_relative '../lib/maze/client/bs_client_utils'
|
16
|
+
require_relative '../lib/maze/client/appium'
|
17
|
+
require_relative '../lib/maze/client/appium/base_client'
|
18
|
+
require_relative '../lib/maze/client/appium/bb_client'
|
19
|
+
require_relative '../lib/maze/client/appium/bb_devices'
|
20
|
+
require_relative '../lib/maze/client/appium/bs_client'
|
21
|
+
require_relative '../lib/maze/client/appium/bs_legacy_client'
|
22
|
+
require_relative '../lib/maze/client/appium/bs_devices'
|
23
|
+
require_relative '../lib/maze/client/appium/local_client'
|
24
|
+
require_relative '../lib/maze/client/selenium'
|
25
|
+
require_relative '../lib/maze/client/selenium/base_client'
|
26
|
+
require_relative '../lib/maze/client/selenium/bb_client'
|
27
|
+
require_relative '../lib/maze/client/selenium/bs_client'
|
28
|
+
require_relative '../lib/maze/client/selenium/local_client'
|
29
|
+
require_relative '../lib/maze/aws_public_ip'
|
15
30
|
require_relative '../lib/maze/compare'
|
16
31
|
require_relative '../lib/maze/docker'
|
17
32
|
require_relative '../lib/maze/document_server'
|
18
33
|
require_relative '../lib/maze/errors'
|
34
|
+
require_relative '../lib/maze/generator'
|
19
35
|
require_relative '../lib/maze/helper'
|
36
|
+
require_relative '../lib/maze/http_request'
|
20
37
|
require_relative '../lib/maze/logger'
|
21
38
|
require_relative '../lib/maze/macos_utils'
|
39
|
+
require_relative '../lib/maze/maze_output'
|
22
40
|
require_relative '../lib/maze/network'
|
23
41
|
require_relative '../lib/maze/proxy'
|
24
42
|
require_relative '../lib/maze/retry_handler'
|
43
|
+
require_relative '../lib/maze/request_repeater'
|
25
44
|
require_relative '../lib/maze/runner'
|
26
|
-
require_relative '../lib/maze/sauce_labs_utils'
|
27
|
-
require_relative '../lib/maze/smart_bear_utils'
|
28
45
|
require_relative '../lib/maze/terminating_server'
|
29
46
|
|
30
47
|
require_relative '../lib/maze/servlets/base_servlet'
|
31
48
|
require_relative '../lib/maze/servlets/command_servlet'
|
32
49
|
require_relative '../lib/maze/servlets/servlet'
|
33
50
|
require_relative '../lib/maze/servlets/log_servlet'
|
51
|
+
require_relative '../lib/maze/servlets/trace_servlet'
|
34
52
|
require_relative '../lib/maze/servlets/reflective_servlet'
|
35
53
|
require_relative '../lib/maze/server'
|
36
54
|
|
55
|
+
require_relative '../lib/maze/assertions/request_set_assertions'
|
56
|
+
|
57
|
+
require_relative '../lib/maze/schemas/trace_schema'
|
58
|
+
require_relative '../lib/maze/schemas/trace_validator'
|
59
|
+
|
37
60
|
require_relative '../lib/maze/store'
|
38
61
|
require_relative '../lib/maze/timers'
|
39
62
|
|
@@ -46,21 +69,23 @@ require_relative '../lib/maze/option/processor'
|
|
46
69
|
require_relative '../lib/maze/option/validator'
|
47
70
|
|
48
71
|
|
49
|
-
require_relative '../lib/maze/assertions/request_set_assertions'
|
50
|
-
|
51
72
|
require_relative '../lib/maze/hooks/hooks'
|
52
73
|
require_relative '../lib/maze/hooks/appium_hooks'
|
53
74
|
require_relative '../lib/maze/hooks/browser_hooks'
|
54
75
|
require_relative '../lib/maze/hooks/command_hooks'
|
76
|
+
require_relative '../lib/maze/hooks/error_code_hook'
|
55
77
|
|
56
78
|
require_relative '../lib/maze/driver/appium'
|
57
79
|
require_relative '../lib/maze/driver/browser'
|
58
|
-
require_relative '../lib/maze/driver/resilient_appium'
|
59
80
|
|
60
81
|
require_relative '../lib/maze/plugins/bugsnag_reporting_plugin'
|
61
82
|
require_relative '../lib/maze/plugins/cucumber_report_plugin'
|
83
|
+
require_relative '../lib/maze/plugins/error_code_plugin'
|
62
84
|
require_relative '../lib/maze/plugins/global_retry_plugin'
|
63
85
|
|
86
|
+
# Require monkey-patches after everything else
|
87
|
+
require_relative '../lib/utils/selenium_money_patch'
|
88
|
+
|
64
89
|
# Encapsulates the MazeRunner entry point
|
65
90
|
class MazeRunnerEntry
|
66
91
|
|
@@ -105,13 +130,26 @@ class MazeRunnerEntry
|
|
105
130
|
options = Maze::Option::Parser.parse args
|
106
131
|
|
107
132
|
if options[Maze::Option::LIST_DEVICES]
|
108
|
-
case options[Maze::Option::FARM]
|
133
|
+
case options[Maze::Option::FARM].to_sym
|
109
134
|
when :bs
|
110
|
-
Maze::BrowserStackDevices.list_devices('ios')
|
111
|
-
Maze::BrowserStackDevices.list_devices('android')
|
135
|
+
Maze::Client::Appium::BrowserStackDevices.list_devices('ios')
|
136
|
+
Maze::Client::Appium::BrowserStackDevices.list_devices('android')
|
137
|
+
when :bb
|
138
|
+
unless options[Maze::Option::ACCESS_KEY]
|
139
|
+
puts 'Listing BitBar devices or device groups available requires a valid access key'
|
140
|
+
exit 1
|
141
|
+
end
|
142
|
+
access_key = options[Maze::Option::ACCESS_KEY]
|
143
|
+
if options[Maze::Option::DEVICE] && !options[Maze::Option::DEVICE].empty?
|
144
|
+
options[Maze::Option::DEVICE].each do |device_group|
|
145
|
+
Maze::Client::Appium::BitBarDevices.list_devices_for_group(device_group, access_key)
|
146
|
+
end
|
147
|
+
else
|
148
|
+
Maze::Client::Appium::BitBarDevices.list_device_groups(access_key)
|
149
|
+
end
|
112
150
|
else
|
113
|
-
Maze::BrowserStackDevices.list_devices('ios')
|
114
|
-
Maze::BrowserStackDevices.list_devices('android')
|
151
|
+
Maze::Client::Appium::BrowserStackDevices.list_devices('ios')
|
152
|
+
Maze::Client::Appium::BrowserStackDevices.list_devices('android')
|
115
153
|
end
|
116
154
|
exit 0
|
117
155
|
end
|
data/bin/upload-app
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require_relative '../lib/maze'
|
5
|
-
require_relative '../lib/maze/
|
5
|
+
require_relative '../lib/maze/client/bs_client_utils'
|
6
6
|
require_relative '../lib/maze/logger'
|
7
7
|
require_relative '../lib/maze/helper'
|
8
8
|
require 'optimist'
|
@@ -45,12 +45,12 @@ class UploadAppEntry
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
Maze::
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
Maze::Client::BrowserStackClientUtils.upload_app username,
|
49
|
+
access_key,
|
50
|
+
opts[:app],
|
51
|
+
opts[:app_id_file]
|
52
52
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
UploadAppEntry.new.start(ARGV)
|
56
|
+
UploadAppEntry.new.start(ARGV)
|
@@ -1,16 +1,41 @@
|
|
1
1
|
# @!group Breadcrumb steps
|
2
2
|
|
3
|
+
# Tests whether the first event entry contains the specified number of breadcrumbs.
|
4
|
+
#
|
5
|
+
# @step_input expected [Integer] The expected number of breadcrumbs
|
6
|
+
Then("the event has {int} breadcrumb(s)") do |expected|
|
7
|
+
breadcrumbs = Maze::Server.errors.current[:body]['events'].first['breadcrumbs']
|
8
|
+
|
9
|
+
Maze.check.equal(
|
10
|
+
expected,
|
11
|
+
breadcrumbs&.length || 0,
|
12
|
+
"Expected event to have '#{expected}' breadcrumbs, but got: #{breadcrumbs}"
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Tests whether the first event entry contains no breadcrumbs.
|
17
|
+
Then("the event has no breadcrumbs") do
|
18
|
+
breadcrumbs = Maze::Server.errors.current[:body]['events'].first['breadcrumbs']
|
19
|
+
|
20
|
+
Maze.check.true(
|
21
|
+
# some notifiers may omit breadcrumbs entirely when empty, otherwise it should
|
22
|
+
# be an empty array
|
23
|
+
breadcrumbs.nil? || breadcrumbs.empty?,
|
24
|
+
"Expected event not to have breadcrumbs, but got: #{breadcrumbs}"
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
3
28
|
# Tests whether the first event entry contains a specific breadcrumb with a type and name.
|
4
29
|
#
|
5
30
|
# @step_input type [String] The expected breadcrumb's type
|
6
31
|
# @step_input name [String] The expected breadcrumb's name
|
7
32
|
Then('the event has a {string} breadcrumb named {string}') do |type, name|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
33
|
+
breadcrumbs = Maze::Server.errors.current[:body]['events'].first['breadcrumbs']
|
34
|
+
|
35
|
+
Maze.check.true(
|
36
|
+
breadcrumbs.any? { |crumb| crumb['type'] == type && crumb['name'] == name },
|
37
|
+
"Expected event to have a breadcrumb with type '#{type}' and name '#{name}', but got: #{breadcrumbs}"
|
38
|
+
)
|
14
39
|
end
|
15
40
|
|
16
41
|
# Tests whether the first event entry contains a specific breadcrumb with a type and message.
|
@@ -19,10 +44,7 @@ end
|
|
19
44
|
# @step_input message [String] The expected breadcrumb's message
|
20
45
|
Then('the event has a {string} breadcrumb with message {string}') do |type, message|
|
21
46
|
value = Maze::Server.errors.current[:body]['events'].first['breadcrumbs']
|
22
|
-
found =
|
23
|
-
value.each do |crumb|
|
24
|
-
found = true if crumb['type'] == type && crumb['metaData'] && crumb['metaData']['message'] == message
|
25
|
-
end
|
47
|
+
found = value.any? { |crumb| crumb['type'] == type && crumb['metaData'] && crumb['metaData']['message'] == message }
|
26
48
|
raise("No breadcrumb matched: #{value}") unless found
|
27
49
|
end
|
28
50
|
|
@@ -32,13 +54,21 @@ end
|
|
32
54
|
# @step_input type [String] The type of breadcrumb expected to not be present
|
33
55
|
Then('the event does not have a {string} breadcrumb') do |type|
|
34
56
|
value = Maze::Server.errors.current[:body]['events'].first['breadcrumbs']
|
35
|
-
found =
|
36
|
-
value.each do |crumb|
|
37
|
-
found = true if crumb['type'] == type
|
38
|
-
end
|
57
|
+
found = value.any? { |crumb| crumb['type'] == type }
|
39
58
|
raise("Breadcrumb with type: #{type} matched") if found
|
40
59
|
end
|
41
60
|
|
61
|
+
# Test whether the first event entry does not contain a breadcrumb with a specific type and message.
|
62
|
+
# Used for confirming filtering of breadcrumbs
|
63
|
+
#
|
64
|
+
# @step_input type [String] The type of the breadcrumb expected to be absent
|
65
|
+
# @step_input message [String] The message of the breadcrumb expected to be absent
|
66
|
+
Then('the event does not have a {string} breadcrumb with message {string}') do |type, message|
|
67
|
+
value = Maze::Server.errors.current[:body]['events'].first['breadcrumbs']
|
68
|
+
found = value.any? { |crumb| crumb['type'] == type && crumb['metaData'] && crumb['metaData']['message'] == message }
|
69
|
+
raise("Breadcrumb with type: #{type} and message: #{message} matched") if found
|
70
|
+
end
|
71
|
+
|
42
72
|
# Tests whether any breadcrumb matches a given JSON fixture. This follows all the usual rules for JSON fixture matching.
|
43
73
|
#
|
44
74
|
# @step_input json_fixture [String] A path to the JSON fixture to compare against
|
@@ -120,6 +120,22 @@ Then('the event {string} equals {string}') do |field, string_value|
|
|
120
120
|
step "the error payload field \"events.0.#{field}\" equals \"#{string_value}\""
|
121
121
|
end
|
122
122
|
|
123
|
+
# Tests whether a value in the first event entry matches a floating point value.
|
124
|
+
#
|
125
|
+
# @step_input field [String] The relative location of the value to test
|
126
|
+
# @step_input string_value [String] The string to match against
|
127
|
+
Then('the event {string} equals {float}') do |field, float_value|
|
128
|
+
step "the error payload field \"events.0.#{field}\" equals #{float_value}"
|
129
|
+
end
|
130
|
+
|
131
|
+
# Tests whether a value in the first event entry matches a floating point value, to a given number of decimal places.
|
132
|
+
#
|
133
|
+
# @step_input field [String] The relative location of the value to test
|
134
|
+
# @step_input string_value [String] The string to match against
|
135
|
+
Then('the event {string} equals {float} to {int} decimal place(s)') do |field, float_value, places|
|
136
|
+
step "the error payload field \"events.0.#{field}\" equals #{float_value} to #{places} decimal places"
|
137
|
+
end
|
138
|
+
|
123
139
|
# Tests whether a value in the first event entry equals an integer.
|
124
140
|
#
|
125
141
|
# @step_input field [String] The relative location of the value to test
|
@@ -12,32 +12,92 @@ end
|
|
12
12
|
#
|
13
13
|
# @step_input status_code [Integer] The status code to return
|
14
14
|
When('I set the HTTP status code to {int}') do |status_code|
|
15
|
-
Maze::Server.
|
15
|
+
Maze::Server.set_status_code_generator(Maze::Generator.new [status_code].cycle)
|
16
16
|
end
|
17
17
|
|
18
18
|
# Sets the HTTP status code to be used for the next request
|
19
19
|
#
|
20
20
|
# @step_input status_code [Integer] The status code to return
|
21
21
|
When('I set the HTTP status code for the next request to {int}') do |status_code|
|
22
|
-
Maze::Server.
|
23
|
-
|
22
|
+
Maze::Server.set_status_code_generator(create_defaulting_generator([status_code], Maze::Server::DEFAULT_STATUS_CODE))
|
23
|
+
end
|
24
|
+
|
25
|
+
# Sets the HTTP status code to be used for the next set of requests
|
26
|
+
#
|
27
|
+
# @step_input status_codes [String] A comma separated list of status codes to return
|
28
|
+
When('I set the HTTP status code for the next requests to {string}') do |status_codes|
|
29
|
+
codes = status_codes.split(',').map(&:strip)
|
30
|
+
Maze::Server.set_status_code_generator(create_defaulting_generator(codes, Maze::Server::DEFAULT_STATUS_CODE))
|
31
|
+
end
|
32
|
+
|
33
|
+
# Steps the HTTP status code to be used for all subsequent requests for a given connection type
|
34
|
+
#
|
35
|
+
# @step_input http_verb [String] The type of request this code will be used for
|
36
|
+
# @step_input status_code [Integer] The status code to return
|
37
|
+
When('I set the HTTP status code for {string} requests to {int}') do |http_verb, status_code|
|
38
|
+
raise("Invalid HTTP verb: #{http_verb}") unless Maze::Server::ALLOWED_HTTP_VERBS.include?(http_verb)
|
39
|
+
Maze::Server.set_status_code_generator(Maze::Generator.new([status_code].cycle), http_verb)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Steps the HTTP status code to be used for the next request for a given connection type
|
43
|
+
#
|
44
|
+
# @step_input http_verb [String] The type of request this code will be used for
|
45
|
+
# @step_input status_code [Integer] The status code to return
|
46
|
+
When('I set the HTTP status code for the next {string} request to {int}') do |http_verb, status_code|
|
47
|
+
raise("Invalid HTTP verb: #{http_verb}") unless Maze::Server::ALLOWED_HTTP_VERBS.include?(http_verb)
|
48
|
+
Maze::Server.set_status_code_generator(create_defaulting_generator([status_code], Maze::Server::DEFAULT_STATUS_CODE), http_verb)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Sets the sampling probability to be used for all subsequent trace responses
|
52
|
+
#
|
53
|
+
# @step_input sampling_probability [String] The sampling probability to return
|
54
|
+
When('I set the sampling probability to {string}') do |sampling_probability|
|
55
|
+
Maze::Server.set_sampling_probability_generator(Maze::Generator.new [sampling_probability].cycle)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Sets the sampling probability to be used for the next trace responses
|
59
|
+
#
|
60
|
+
# @step_input status_code [Integer] The status code to return
|
61
|
+
When('I set the sampling probability for the next trace to {string}') do |sampling_probability|
|
62
|
+
Maze::Server.set_sampling_probability_generator(create_defaulting_generator([sampling_probability], Maze::Server::DEFAULT_SAMPLING_PROBABILITY))
|
63
|
+
end
|
64
|
+
|
65
|
+
# Sets the sampling probability to be used for the next set of trace requests
|
66
|
+
#
|
67
|
+
# @step_input sampling_probability [String] A comma separated list of values to use, with "null" used to omit the header
|
68
|
+
When('I set the sampling probability for the next traces to {string}') do |status_codes|
|
69
|
+
codes = status_codes.split(',').map(&:strip)
|
70
|
+
Maze::Server.set_sampling_probability_generator(create_defaulting_generator(codes, Maze::Server::DEFAULT_SAMPLING_PROBABILITY))
|
24
71
|
end
|
25
72
|
|
26
73
|
# Sets the response delay to be used for all subsequent requests
|
27
74
|
#
|
28
75
|
# @step_input response_delay_ms [Integer] The delay in milliseconds
|
29
76
|
When('I set the response delay to {int} milliseconds') do |response_delay_ms|
|
30
|
-
Maze::Server.
|
77
|
+
Maze::Server.set_response_delay_generator(Maze::Generator.new [response_delay_ms].cycle)
|
31
78
|
end
|
32
79
|
|
33
80
|
# Sets the response delay to be used for the next request
|
34
81
|
#
|
35
82
|
# @step_input delay [Integer] The delay in milliseconds
|
36
83
|
When('I set the response delay for the next request to {int} milliseconds') do |delay|
|
37
|
-
Maze::Server.
|
38
|
-
|
84
|
+
Maze::Server.set_response_delay_generator(create_defaulting_generator([delay], Maze::Server::DEFAULT_RESPONSE_DELAY))
|
85
|
+
end
|
86
|
+
|
87
|
+
def create_defaulting_generator(codes, default)
|
88
|
+
enumerator = Enumerator.new do |yielder|
|
89
|
+
codes.each do |code|
|
90
|
+
yielder.yield code
|
91
|
+
end
|
92
|
+
|
93
|
+
loop do
|
94
|
+
yielder.yield default
|
95
|
+
end
|
96
|
+
end
|
97
|
+
Maze::Generator.new enumerator
|
39
98
|
end
|
40
99
|
|
100
|
+
|
41
101
|
# Attempts to open a URL.
|
42
102
|
#
|
43
103
|
# @step_input url [String] The URL to open.
|
@@ -86,6 +86,29 @@ Then('the {word} payload field {string} equals {int}') do |request_type, field_p
|
|
86
86
|
Maze::Helper.read_key_path(Maze::Server.list_for(request_type).current[:body], field_path))
|
87
87
|
end
|
88
88
|
|
89
|
+
# Tests that a payload element equals a float.
|
90
|
+
#
|
91
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
92
|
+
# @step_input field_path [String] Path to the tested element
|
93
|
+
# @step_input float_value [Float] The value to test against
|
94
|
+
Then('the {word} payload field {string} equals {float}') do |request_type, field_path, float_value|
|
95
|
+
Maze.check.equal(float_value,
|
96
|
+
Maze::Helper.read_key_path(Maze::Server.list_for(request_type).current[:body], field_path))
|
97
|
+
end
|
98
|
+
|
99
|
+
# Tests that a payload element equals a float, to a given number of decimal places.
|
100
|
+
#
|
101
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
102
|
+
# @step_input field_path [String] Path to the tested element
|
103
|
+
# @step_input float_value [Float] The value to test against
|
104
|
+
# @step_input places [Int] The number of decimal places to round the actual value to first
|
105
|
+
Then('the {word} payload field {string} equals {float} to {int} decimal place(s)') do |request_type, field_path, float_value, places|
|
106
|
+
body = Maze::Server.list_for(request_type).current[:body]
|
107
|
+
rounded_value = Maze::Helper.read_key_path(body, field_path).round places
|
108
|
+
Maze.check.equal(float_value,
|
109
|
+
rounded_value)
|
110
|
+
end
|
111
|
+
|
89
112
|
# Tests the payload field value against an environment variable.
|
90
113
|
#
|
91
114
|
# @step_input request_type [String] The type of request (error, session, build, etc)
|
@@ -8,15 +8,15 @@ require_relative '../../maze/wait'
|
|
8
8
|
|
9
9
|
# @!group Request assertion steps
|
10
10
|
|
11
|
-
def assert_received_requests(request_count, list, list_name)
|
11
|
+
def assert_received_requests(request_count, list, list_name, precise = true)
|
12
12
|
timeout = Maze.config.receive_requests_wait
|
13
13
|
wait = Maze::Wait.new(timeout: timeout)
|
14
14
|
|
15
|
-
received = wait.until { list.
|
15
|
+
received = wait.until { list.size_remaining >= request_count }
|
16
16
|
|
17
17
|
unless received
|
18
18
|
raise Test::Unit::AssertionFailedError.new <<-MESSAGE
|
19
|
-
Expected #{request_count} #{list_name} but received #{list.
|
19
|
+
Expected #{request_count} #{list_name} but received #{list.size_remaining} within the #{timeout}s timeout.
|
20
20
|
This could indicate that:
|
21
21
|
- Bugsnag crashed with a fatal error.
|
22
22
|
- Bugsnag did not make the requests that it should have done.
|
@@ -26,7 +26,65 @@ def assert_received_requests(request_count, list, list_name)
|
|
26
26
|
MESSAGE
|
27
27
|
end
|
28
28
|
|
29
|
-
|
29
|
+
if precise
|
30
|
+
Maze.check.equal(request_count, list.size_remaining, "#{list.size_remaining} #{list_name} received")
|
31
|
+
else
|
32
|
+
Maze.check.operator(request_count, :<=, list.size_remaining, "#{list.size_remaining} #{list_name} received")
|
33
|
+
end
|
34
|
+
|
35
|
+
verify_schema_matches(list, list_name)
|
36
|
+
validate_payload_elements(list, list_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def verify_schema_matches(list, list_name)
|
40
|
+
request_schema_results = list.all.map { |request| request[:schema_errors] }
|
41
|
+
passed = true
|
42
|
+
request_schema_results.each.with_index(1) do |schema_errors, index|
|
43
|
+
next if schema_errors.nil?
|
44
|
+
if schema_errors.size > 0
|
45
|
+
passed = false
|
46
|
+
$stdout.puts "\n"
|
47
|
+
$stdout.puts "\e[31m--- #{list_name} #{index} failed validation with errors at the following locations:\e[0m"
|
48
|
+
schema_errors.each do |error|
|
49
|
+
$stdout.puts "\e[31m#{error["data_pointer"]} failed to match #{error["schema_pointer"]}\e[0m"
|
50
|
+
end
|
51
|
+
$stdout.puts "\n"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
unless passed
|
56
|
+
raise Test::Unit::AssertionFailedError.new 'The received payloads did not match the endpoint schema. A full list of the errors can be found above'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_payload_elements(list, list_name)
|
61
|
+
validator_class = case list_name
|
62
|
+
when 'trace', 'traces'
|
63
|
+
Maze::Schemas::TraceValidator
|
64
|
+
else
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
|
68
|
+
if validator_class
|
69
|
+
validators = list.all.map do |request|
|
70
|
+
validator = validator_class.new(request[:body])
|
71
|
+
validator.validate
|
72
|
+
validator
|
73
|
+
end
|
74
|
+
|
75
|
+
return if validators.all? { |validator| validator.success }
|
76
|
+
validators.each.with_index(1) do |validator, index|
|
77
|
+
unless validator.success
|
78
|
+
$stdout.puts "\n"
|
79
|
+
$stdout.puts "\e[31m--- #{list_name} #{index} failed validation with the following errors:\e[0m"
|
80
|
+
validator.errors.each do |error|
|
81
|
+
$stdout.puts "\e[31m#{error}\e[0m"
|
82
|
+
end
|
83
|
+
$stdout.puts "\n"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
raise Test::Unit::AssertionFailedError.new("One or more #{list_name} payloads failed validation. A full list of the errors can be found above")
|
87
|
+
end
|
30
88
|
end
|
31
89
|
|
32
90
|
#
|
@@ -52,6 +110,27 @@ Then('I wait to receive {int} {word}') do |request_count, request_type|
|
|
52
110
|
list.sort_by_sent_at! request_count
|
53
111
|
end
|
54
112
|
|
113
|
+
# Continually checks to see if at least the number requests given has been received,
|
114
|
+
# timing out according to @see Maze.config.receive_requests_wait.
|
115
|
+
#
|
116
|
+
# This step can tolerate receiving more than the expected number of requests.
|
117
|
+
#
|
118
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
119
|
+
# @step_input request_count [Integer] The amount of requests expected
|
120
|
+
Then('I wait to receive at least {int} {word}') do |request_count, request_type|
|
121
|
+
list = Maze::Server.list_for(request_type)
|
122
|
+
assert_received_requests request_count, list, request_type, false
|
123
|
+
end
|
124
|
+
|
125
|
+
# Sorts the remaining requests in a list by the field path given.
|
126
|
+
#
|
127
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
128
|
+
# @step_input field_path [String] The field to sort by
|
129
|
+
Then('I sort the {word} by the payload field {string}') do |request_type, field_path|
|
130
|
+
list = Maze::Server.list_for(request_type)
|
131
|
+
list.sort_by! field_path
|
132
|
+
end
|
133
|
+
|
55
134
|
# Verify that at least a certain amount of requests have been received
|
56
135
|
# This step is only intended for use in stress tests
|
57
136
|
#
|
@@ -59,7 +138,7 @@ end
|
|
59
138
|
# @step_input request_type [String] The type of request (error, session, build, etc)
|
60
139
|
Then('I have received at least {int} {word}') do |min_received, request_type|
|
61
140
|
list = Maze::Server.list_for(request_type)
|
62
|
-
Maze.check.operator(list.
|
141
|
+
Maze.check.operator(list.size_remaining, :>=, min_received, "Actually received #{list.size_remaining} #{request_type} requests")
|
63
142
|
end
|
64
143
|
|
65
144
|
# Assert that the test Server hasn't received any requests - of a specific, or any, type.
|
@@ -70,11 +149,11 @@ Then('I should receive no {word}') do |request_type|
|
|
70
149
|
sleep Maze.config.receive_no_requests_wait
|
71
150
|
if request_type == 'requests'
|
72
151
|
# Assert that the test Server hasn't received any requests at all.
|
73
|
-
Maze.check.equal(0, Maze::Server.errors.
|
74
|
-
Maze.check.equal(0, Maze::Server.sessions.
|
152
|
+
Maze.check.equal(0, Maze::Server.errors.size_remaining, "#{Maze::Server.errors.size_remaining} errors received")
|
153
|
+
Maze.check.equal(0, Maze::Server.sessions.size_remaining, "#{Maze::Server.sessions.size_remaining} sessions received")
|
75
154
|
else
|
76
155
|
list = Maze::Server.list_for(request_type)
|
77
|
-
Maze.check.equal(0, list.
|
156
|
+
Maze.check.equal(0, list.size_remaining, "#{list.size_remaining} #{request_type} received")
|
78
157
|
end
|
79
158
|
end
|
80
159
|
|
@@ -97,6 +97,28 @@ When('I run the service {string} with the command') do |service, command|
|
|
97
97
|
Maze::Docker.start_service(service, command: one_line_cmd)
|
98
98
|
end
|
99
99
|
|
100
|
+
# Executes a command in the given docker compose service.
|
101
|
+
#
|
102
|
+
# The service must already be running for this to succeed as it uses 'docker
|
103
|
+
# compose exec'.
|
104
|
+
#
|
105
|
+
# @step_input command [String] The command to run inside the service
|
106
|
+
# @step_input service [String] The name of the service
|
107
|
+
When('I execute the command {string} in the service {string}') do |command, service|
|
108
|
+
Maze::Docker.exec(service, command)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Executes a command in the given docker compose service in the background.
|
112
|
+
#
|
113
|
+
# The service must already be running for this to succeed as it uses 'docker
|
114
|
+
# compose exec --detach'.
|
115
|
+
#
|
116
|
+
# @step_input command [String] The command to run inside the service
|
117
|
+
# @step_input service [String] The name of the service
|
118
|
+
When('I execute the command {string} in the service {string} in the background') do |command, service|
|
119
|
+
Maze::Docker.exec(service, command, detach: true)
|
120
|
+
end
|
121
|
+
|
100
122
|
# Allows validation of the last exit code of the last run docker-compose command.
|
101
123
|
# Will fail if no commands have been run.
|
102
124
|
#
|
@@ -36,7 +36,7 @@ Then('the session is valid for the session reporting API version {string} for th
|
|
36
36
|
And the session "Content-Type" header equals "application/json"
|
37
37
|
And the session "Bugsnag-Sent-At" header is a timestamp
|
38
38
|
|
39
|
-
And the session payload field "notifier.name" matches the regex "(Android|iOS) Bugsnag Notifier"
|
39
|
+
And the session payload field "notifier.name" matches the regex "(Bugsnag React Native|(Android|iOS) Bugsnag Notifier)"
|
40
40
|
And the session payload field "notifier.url" is not null
|
41
41
|
And the session payload field "notifier.version" is not null
|
42
42
|
|