bugsnag-maze-runner 6.27.0 → 7.22.1
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 +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
|
|