bugsnag-maze-runner 7.22.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/bugsnag-print-load-paths +6 -0
- data/bin/download-logs +74 -0
- data/bin/maze-runner +174 -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 +80 -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 +358 -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 +135 -0
- data/lib/features/steps/payload_steps.rb +257 -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 +186 -0
- data/lib/features/steps/runner_steps.rb +428 -0
- data/lib/features/steps/session_tracking_steps.rb +116 -0
- data/lib/features/steps/trace_steps.rb +206 -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 +207 -0
- data/lib/maze/api/appium/file_manager.rb +29 -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/aws_public_ip.rb +53 -0
- data/lib/maze/bugsnag_config.rb +42 -0
- data/lib/maze/checks/assert_check.rb +69 -0
- data/lib/maze/checks/noop_check.rb +34 -0
- 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/compare.rb +161 -0
- data/lib/maze/configuration.rb +182 -0
- data/lib/maze/docker.rb +147 -0
- data/lib/maze/document_server.rb +46 -0
- data/lib/maze/driver/appium.rb +198 -0
- data/lib/maze/driver/browser.rb +124 -0
- data/lib/maze/errors.rb +52 -0
- data/lib/maze/generator.rb +55 -0
- data/lib/maze/helper.rb +122 -0
- data/lib/maze/hooks/appium_hooks.rb +55 -0
- data/lib/maze/hooks/browser_hooks.rb +15 -0
- data/lib/maze/hooks/command_hooks.rb +9 -0
- data/lib/maze/hooks/error_code_hook.rb +49 -0
- data/lib/maze/hooks/hooks.rb +61 -0
- data/lib/maze/http_request.rb +21 -0
- data/lib/maze/interactive_cli.rb +173 -0
- data/lib/maze/logger.rb +86 -0
- data/lib/maze/macos_utils.rb +14 -0
- data/lib/maze/maze_output.rb +88 -0
- data/lib/maze/network.rb +49 -0
- data/lib/maze/option/parser.rb +240 -0
- data/lib/maze/option/processor.rb +130 -0
- data/lib/maze/option/validator.rb +155 -0
- data/lib/maze/option.rb +62 -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/error_code_plugin.rb +21 -0
- data/lib/maze/plugins/global_retry_plugin.rb +38 -0
- data/lib/maze/proxy.rb +114 -0
- data/lib/maze/request_list.rb +87 -0
- data/lib/maze/request_repeater.rb +49 -0
- data/lib/maze/retry_handler.rb +67 -0
- data/lib/maze/runner.rb +149 -0
- 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 +251 -0
- data/lib/maze/servlets/base_servlet.rb +27 -0
- data/lib/maze/servlets/command_servlet.rb +47 -0
- data/lib/maze/servlets/log_servlet.rb +64 -0
- data/lib/maze/servlets/reflective_servlet.rb +70 -0
- data/lib/maze/servlets/servlet.rb +199 -0
- data/lib/maze/servlets/temp.rb +0 -0
- data/lib/maze/servlets/trace_servlet.rb +13 -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
- data/lib/utils/deep_merge.rb +17 -0
- data/lib/utils/selenium_money_patch.rb +17 -0
- metadata +451 -0
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'json'
|
4
|
+
require 'cgi'
|
5
|
+
|
6
|
+
# @!group Multipart request assertion steps
|
7
|
+
|
8
|
+
# Verifies a request contains the correct Content-Type header and some contents
|
9
|
+
# for a multipart/form-data request
|
10
|
+
#
|
11
|
+
# @param request [Hash] The payload to test
|
12
|
+
def valid_multipart_form_data?(request)
|
13
|
+
content_regex = Regexp.new('^multipart\\/form-data; boundary=[\\h-]+$')
|
14
|
+
content_header = request[:request]['Content-Type']
|
15
|
+
Maze.check.match(content_regex, content_header)
|
16
|
+
Maze.check.true(
|
17
|
+
request[:body].size.positive?,
|
18
|
+
"Multipart request payload contained #{request[:body].size} fields"
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Verifies that any type of request contains multipart form-data
|
23
|
+
#
|
24
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
25
|
+
Then('the {word} request is valid multipart form-data') do |request_type|
|
26
|
+
list = Maze::Server.list_for request_type
|
27
|
+
valid_multipart_form_data?(list.current)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Verifies all requests of a given type contain multipart form-data
|
31
|
+
#
|
32
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
33
|
+
Then('all {word} requests are valid multipart form-data') do |request_type|
|
34
|
+
list = Maze::Server.list_for request_type
|
35
|
+
list.all.all? { |request| valid_multipart_form_data?(request) }
|
36
|
+
end
|
37
|
+
|
38
|
+
# Tests the number of fields a given type of multipart request contains.
|
39
|
+
#
|
40
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
41
|
+
# @step_input part_count [Integer] The number of expected fields
|
42
|
+
Then('the {word} multipart request has {int} fields') do |request_type, part_count|
|
43
|
+
list = Maze::Server.list_for request_type
|
44
|
+
parts = list.current[:body]
|
45
|
+
Maze.check.equal(part_count, parts.size)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Tests a given type of multipart request has at least one field.
|
49
|
+
#
|
50
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
51
|
+
Then('the {word} multipart request has a non-empty body') do |request_type|
|
52
|
+
list = Maze::Server.list_for request_type
|
53
|
+
parts = list.current[:body]
|
54
|
+
Maze.check.true(parts.size.positive?, "Multipart request payload contained #{parts.size} fields")
|
55
|
+
end
|
56
|
+
|
57
|
+
# Takes a hashmap and parses all fields into strings or hashes depending on their format
|
58
|
+
# Used to convert a multipart/form-data request into a JSON comparable hash
|
59
|
+
#
|
60
|
+
# @param body [Hash] The multipart/form-data hash to parse
|
61
|
+
#
|
62
|
+
# @return [Hash] The result of parsing hash fields to strings/JSON hashes
|
63
|
+
def parse_multipart_body(body)
|
64
|
+
body.each_with_object({}) do |(k, v), out|
|
65
|
+
out[k] = JSON.parse(v.to_s)
|
66
|
+
rescue JSON::ParserError
|
67
|
+
out[k] = v.to_s
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Tests that a given type of multipart payload body does not match a JSON file.
|
72
|
+
# JSON formatted multipart fields will be parsed into hashes.
|
73
|
+
#
|
74
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
75
|
+
# @step_input json_path [String] Path to a JSON file relative to maze-runner root
|
76
|
+
Then('the {word} multipart body does not match the JSON file in {string}') do |request_type, json_path|
|
77
|
+
Maze.check.true(File.exist?(json_path), "'#{json_path}' does not exist")
|
78
|
+
payload_list = Maze::Server.list_for request_type
|
79
|
+
raw_payload_value = payload_list.current[:body]
|
80
|
+
payload_value = parse_multipart_body(raw_payload_value)
|
81
|
+
expected_value = JSON.parse(open(json_path, &:read))
|
82
|
+
result = Maze::Compare.value(expected_value, payload_value)
|
83
|
+
Maze.check.false(result.equal?, "Payload:\n#{payload_value}\nExpected:#{expected_value}")
|
84
|
+
end
|
85
|
+
|
86
|
+
# Tests that a given type of multipart payload body matches a JSON fixture.
|
87
|
+
# JSON formatted multipart fields will be parsed into hashes.
|
88
|
+
#
|
89
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
90
|
+
# @step_input json_path [String] Path to a JSON file relative to maze-runner root
|
91
|
+
Then('the {word} multipart body matches the JSON file in {string}') do |request_type, json_path|
|
92
|
+
Maze.check.true(File.exist?(json_path), "'#{json_path}' does not exist")
|
93
|
+
payload_list = Maze::Server.list_for request_type
|
94
|
+
raw_payload_value = payload_list.current[:body]
|
95
|
+
payload_value = parse_multipart_body(raw_payload_value)
|
96
|
+
expected_value = JSON.parse(open(json_path, &:read))
|
97
|
+
result = Maze::Compare.value(expected_value, payload_value)
|
98
|
+
Maze.check.true(result.equal?, "The payload field '#{result.keypath}' does not match the fixture:\n #{result.reasons.join('\n')}")
|
99
|
+
end
|
100
|
+
|
101
|
+
# Tests that a given type of multipart field matches a JSON fixture.
|
102
|
+
# The field will be parsed into a hash.
|
103
|
+
#
|
104
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
105
|
+
# @step_input field_path [String] Path to the tested element
|
106
|
+
# @step_input json_path [String] Path to a JSON file relative to maze-runner root
|
107
|
+
Then('the {word} multipart field {string} matches the JSON file in {string}') do |request_type, field_path, json_path|
|
108
|
+
Maze.check.true(File.exist?(json_path), "'#{json_path}' does not exist")
|
109
|
+
payload_list = Maze::Server.list_for request_type
|
110
|
+
payload_value = JSON.parse(payload_list.current[:body][field_path].to_s)
|
111
|
+
expected_value = JSON.parse(open(json_path, &:read))
|
112
|
+
result = Maze::Compare.value(expected_value, payload_value)
|
113
|
+
Maze.check.true(result.equal?, "The multipart field '#{result.keypath}' does not match the fixture:\n #{result.reasons.join('\n')}")
|
114
|
+
end
|
115
|
+
|
116
|
+
# Tests that a multipart request field exists and is not null.
|
117
|
+
#
|
118
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
119
|
+
# @step_input part_key [String] The key to the multipart element
|
120
|
+
Then('the field {string} for multipart {word} is not null') do |part_key, request_type|
|
121
|
+
parts = Maze::Server.list_for(request_type).current[:body]
|
122
|
+
Maze.check.not_nil(parts[part_key], "The field '#{part_key}' should not be null")
|
123
|
+
end
|
124
|
+
|
125
|
+
# Tests that a multipart request field exists and is null.
|
126
|
+
#
|
127
|
+
# @step_input part_key [String] The key to the multipart element
|
128
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
129
|
+
Then('the field {string} for multipart {word} is null') do |part_key, request_type|
|
130
|
+
parts = Maze::Server.list_for(request_type).current[:body]
|
131
|
+
Maze.check.nil(parts[part_key], "The field '#{part_key}' should be null")
|
132
|
+
end
|
133
|
+
|
134
|
+
# Tests that a multipart request field equals a string.
|
135
|
+
#
|
136
|
+
# @step_input part_key [String] The key to the multipart element
|
137
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
138
|
+
# @step_input expected_value [String] The string to match against
|
139
|
+
Then('the field {string} for multipart {word} equals {string}') do |part_key, request_type, expected_value|
|
140
|
+
parts = Maze::Server.list_for(request_type).current[:body]
|
141
|
+
Maze.check.equal(parts[part_key], expected_value)
|
142
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# @!group Network steps
|
2
|
+
|
3
|
+
# Checks that a port on a given host is open and ready for connections.
|
4
|
+
#
|
5
|
+
# @step_input host [String] The host to check
|
6
|
+
# @step_input port [String] The port to check
|
7
|
+
When('I wait for the host {string} to open port {string}') do |host, port|
|
8
|
+
Maze::Network.wait_for_port(host, port)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Sets the HTTP status code to be used for all subsequent requests
|
12
|
+
#
|
13
|
+
# @step_input status_code [Integer] The status code to return
|
14
|
+
When('I set the HTTP status code to {int}') do |status_code|
|
15
|
+
Maze::Server.set_status_code_generator(Maze::Generator.new [status_code].cycle)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Sets the HTTP status code to be used for the next request
|
19
|
+
#
|
20
|
+
# @step_input status_code [Integer] The status code to return
|
21
|
+
When('I set the HTTP status code for the next request to {int}') do |status_code|
|
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))
|
71
|
+
end
|
72
|
+
|
73
|
+
# Sets the response delay to be used for all subsequent requests
|
74
|
+
#
|
75
|
+
# @step_input response_delay_ms [Integer] The delay in milliseconds
|
76
|
+
When('I set the response delay to {int} milliseconds') do |response_delay_ms|
|
77
|
+
Maze::Server.set_response_delay_generator(Maze::Generator.new [response_delay_ms].cycle)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Sets the response delay to be used for the next request
|
81
|
+
#
|
82
|
+
# @step_input delay [Integer] The delay in milliseconds
|
83
|
+
When('I set the response delay for the next request to {int} milliseconds') do |delay|
|
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
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
# Attempts to open a URL.
|
102
|
+
#
|
103
|
+
# @step_input url [String] The URL to open.
|
104
|
+
When('I open the URL {string}') do |url|
|
105
|
+
begin
|
106
|
+
open(url, &:read)
|
107
|
+
rescue OpenURI::HTTPError
|
108
|
+
$logger.debug $!.inspect
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Starts the terminating server to cancel requests received.
|
113
|
+
When('I start the terminating server') do
|
114
|
+
Maze::TerminatingServer.start
|
115
|
+
end
|
116
|
+
|
117
|
+
# Sets the response message on the terminating server
|
118
|
+
When('I set the terminated response message to {string}') do |response_message|
|
119
|
+
Maze::TerminatingServer.response = response_message
|
120
|
+
end
|
121
|
+
|
122
|
+
# Sets the maximum allowable amount of data received to the terminating server
|
123
|
+
#
|
124
|
+
# @step_input max_length [Integer] The number of bytes receivable
|
125
|
+
When('I set the terminating server data threshold to {int} bytes') do |max_length|
|
126
|
+
Maze::TerminatingServer.max_received_size = max_length
|
127
|
+
end
|
128
|
+
|
129
|
+
# Check if a certain number of connections have been received by the terminating server
|
130
|
+
#
|
131
|
+
# @step_input request_count [Integer] The number of desired requests
|
132
|
+
Then('the terminating server has received {int} requests') do |request_count|
|
133
|
+
Maze.check.equal(request_count, Maze::TerminatingServer.received_request_count,
|
134
|
+
"#{request_count} terminated requests expected, #{Maze::TerminatingServer.received_request_count} received")
|
135
|
+
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @!group Payload steps
|
4
|
+
|
5
|
+
# Tests the payload body does not match a JSON fixture.
|
6
|
+
#
|
7
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
8
|
+
# @step_input fixture_path [String] Path to a JSON fixture
|
9
|
+
Then('the {word} payload body does not match the JSON fixture in {string}') do |request_type, fixture_path|
|
10
|
+
payload_value = Maze::Server.list_for(request_type).current[:body]
|
11
|
+
expected_value = JSON.parse(open(fixture_path, &:read))
|
12
|
+
result = Maze::Compare.value(expected_value, payload_value)
|
13
|
+
Maze.check.false(result.equal?, "Payload:\n#{payload_value}\nExpected:#{expected_value}")
|
14
|
+
end
|
15
|
+
|
16
|
+
# Test the payload body matches a JSON fixture.
|
17
|
+
#
|
18
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
19
|
+
# @step_input fixture_path [String] Path to a JSON fixture
|
20
|
+
Then('the {word} payload body matches the JSON fixture in {string}') do |request_type, fixture_path|
|
21
|
+
payload_value = Maze::Server.list_for(request_type).current[:body]
|
22
|
+
expected_value = JSON.parse(open(fixture_path, &:read))
|
23
|
+
result = Maze::Compare.value(expected_value, payload_value)
|
24
|
+
Maze.check.true(result.equal?,
|
25
|
+
"The payload field '#{result.keypath}' does not match the fixture:\n #{result.reasons.join('\n')}")
|
26
|
+
end
|
27
|
+
|
28
|
+
# Test that a payload element matches a JSON fixture.
|
29
|
+
#
|
30
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
31
|
+
# @step_input field_path [String] Path to the tested element
|
32
|
+
# @step_input fixture_path [String] Path to a JSON fixture
|
33
|
+
Then('the {word} payload field {string} matches the JSON fixture in {string}') \
|
34
|
+
do |request_type, field_path, fixture_path|
|
35
|
+
list = Maze::Server.list_for(request_type)
|
36
|
+
payload_value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
37
|
+
expected_value = JSON.parse(open(fixture_path, &:read))
|
38
|
+
result = Maze::Compare.value(expected_value, payload_value)
|
39
|
+
Maze.check.true(result.equal?,
|
40
|
+
"The payload field '#{result.keypath}' does not match the fixture:\n #{result.reasons.join('\n')}")
|
41
|
+
end
|
42
|
+
|
43
|
+
# Tests that a request element is true.
|
44
|
+
#
|
45
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
46
|
+
# @step_input field_path [String] Path to the tested element
|
47
|
+
Then('the {word} payload field {string} is true') do |request_type, field_path|
|
48
|
+
list = Maze::Server.list_for(request_type)
|
49
|
+
Maze.check.true(Maze::Helper.read_key_path(list.current[:body], field_path))
|
50
|
+
end
|
51
|
+
|
52
|
+
# Tests that a request element is false.
|
53
|
+
#
|
54
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
55
|
+
# @step_input field_path [String] Path to the tested element
|
56
|
+
Then('the {word} payload field {string} is false') do |request_type, field_path|
|
57
|
+
list = Maze::Server.list_for(request_type)
|
58
|
+
Maze.check.false(Maze::Helper.read_key_path(list.current[:body], field_path))
|
59
|
+
end
|
60
|
+
|
61
|
+
# Tests that a request element is null.
|
62
|
+
#
|
63
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
64
|
+
# @step_input field_path [String] Path to the tested element
|
65
|
+
Then('the {word} payload field {string} is null') do |request_type, field_path|
|
66
|
+
list = Maze::Server.list_for(request_type)
|
67
|
+
Maze.check.nil(Maze::Helper.read_key_path(list.current[:body], field_path))
|
68
|
+
end
|
69
|
+
|
70
|
+
# Tests that a request element is not null.
|
71
|
+
#
|
72
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
73
|
+
# @step_input field_path [String] Path to the tested element
|
74
|
+
Then('the {word} payload field {string} is not null') do |request_type, field_path|
|
75
|
+
list = Maze::Server.list_for(request_type)
|
76
|
+
Maze.check.not_nil(Maze::Helper.read_key_path(list.current[:body], field_path))
|
77
|
+
end
|
78
|
+
|
79
|
+
# Tests that a payload element equals an integer.
|
80
|
+
#
|
81
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
82
|
+
# @step_input field_path [String] Path to the tested element
|
83
|
+
# @step_input int_value [Integer] The value to test against
|
84
|
+
Then('the {word} payload field {string} equals {int}') do |request_type, field_path, int_value|
|
85
|
+
Maze.check.equal(int_value,
|
86
|
+
Maze::Helper.read_key_path(Maze::Server.list_for(request_type).current[:body], field_path))
|
87
|
+
end
|
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
|
+
|
112
|
+
# Tests the payload field value against an environment variable.
|
113
|
+
#
|
114
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
115
|
+
# @step_input field_path [String] The payload element to test
|
116
|
+
# @step_input env_var [String] The environment variable to test against
|
117
|
+
Then('the {word} payload field {string} equals the environment variable {string}') \
|
118
|
+
do |request_type, field_path, env_var|
|
119
|
+
environment_value = ENV[env_var]
|
120
|
+
Maze.check.false(environment_value.nil?, "The environment variable #{env_var} must not be nil")
|
121
|
+
list = Maze::Server.list_for(request_type)
|
122
|
+
value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
123
|
+
|
124
|
+
Maze.check.equal(environment_value, value)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Tests a payload field contains a number larger than a value.
|
128
|
+
#
|
129
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
130
|
+
# @step_input field_path [String] The payload element to test
|
131
|
+
# @step_input int_value [Integer] The value to compare against
|
132
|
+
Then('the {word} payload field {string} is greater than {int}') do |request_type, field_path, int_value|
|
133
|
+
list = Maze::Server.list_for(request_type)
|
134
|
+
value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
135
|
+
Maze.check.kind_of Integer, value
|
136
|
+
Maze.check.operator(value, :>, int_value, "The payload field '#{field_path}' (#{value}) is not greater than '#{int_value}'")
|
137
|
+
end
|
138
|
+
|
139
|
+
# Tests a payload field contains a number smaller than a value.
|
140
|
+
#
|
141
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
142
|
+
# @step_input field_path [String] The payload element to test
|
143
|
+
# @step_input int_value [Integer] The value to compare against
|
144
|
+
Then('the {word} payload field {string} is less than {int}') do |request_type, field_path, int_value|
|
145
|
+
list = Maze::Server.list_for(request_type)
|
146
|
+
value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
147
|
+
Maze.check.kind_of Integer, value
|
148
|
+
fail_message = "The #{request_type} payload field '#{field_path}' (#{value}) is not less than '#{int_value}'"
|
149
|
+
Maze.check.operator(value, :<, int_value, fail_message)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Tests a payload field equals a string.
|
153
|
+
#
|
154
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
155
|
+
# @step_input field_path [String] The payload element to test
|
156
|
+
# @step_input string_value [String] The string to test against
|
157
|
+
Then('the {word} payload field {string} equals {string}') do |request_type, field_path, string_value|
|
158
|
+
list = Maze::Server.list_for(request_type)
|
159
|
+
Maze.check.equal(string_value, Maze::Helper.read_key_path(list.current[:body], field_path))
|
160
|
+
end
|
161
|
+
|
162
|
+
# Tests a payload field starts with a string.
|
163
|
+
#
|
164
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
165
|
+
# @step_input field_path [String] The payload element to test
|
166
|
+
# @step_input string_value [String] The string to test against
|
167
|
+
Then('the {word} payload field {string} starts with {string}') do |request_type, field_path, string_value|
|
168
|
+
list = Maze::Server.list_for(request_type)
|
169
|
+
value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
170
|
+
Maze.check.kind_of String, value
|
171
|
+
Maze.check.true(
|
172
|
+
value.start_with?(string_value),
|
173
|
+
"Field '#{field_path}' value ('#{value}') does not start with '#{string_value}'"
|
174
|
+
)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Tests a payload field ends with a string.
|
178
|
+
#
|
179
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
180
|
+
# @step_input field_path [String] The payload element to test
|
181
|
+
# @step_input string_value [String] The string to test against
|
182
|
+
Then('the {word} payload field {string} ends with {string}') do |request_type, field_path, string_value|
|
183
|
+
list = Maze::Server.list_for(request_type)
|
184
|
+
value = Maze::Helper.read_key_path(list.current[:body], field_path)
|
185
|
+
Maze.check.kind_of String, value
|
186
|
+
Maze.check.true(
|
187
|
+
value.end_with?(string_value),
|
188
|
+
"Field '#{field_path}' value ('#{value}') does not end with '#{string_value}'"
|
189
|
+
)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Tests a payload field is an array with a specific element count.
|
193
|
+
#
|
194
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
195
|
+
# @step_input field [String] The payload element to test
|
196
|
+
# @step_input count [Integer] The value expected
|
197
|
+
Then('the {word} payload field {string} is an array with {int} elements') do |request_type, field, count|
|
198
|
+
list = Maze::Server.list_for(request_type)
|
199
|
+
value = Maze::Helper.read_key_path(list.current[:body], field)
|
200
|
+
Maze.check.kind_of Array, value
|
201
|
+
Maze.check.equal(count, value.length)
|
202
|
+
end
|
203
|
+
|
204
|
+
# Tests a payload field is an array with at least one element.
|
205
|
+
#
|
206
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
207
|
+
# @step_input field [String] The payload element to test
|
208
|
+
Then('the {word} payload field {string} is a non-empty array') do |request_type, field|
|
209
|
+
list = Maze::Server.list_for(request_type)
|
210
|
+
value = Maze::Helper.read_key_path(list.current[:body], field)
|
211
|
+
Maze.check.kind_of Array, value
|
212
|
+
Maze.check.true(value.length.positive?, "the field '#{field}' must be a non-empty array")
|
213
|
+
end
|
214
|
+
|
215
|
+
# Tests a payload field matches a regex.
|
216
|
+
#
|
217
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
218
|
+
# @step_input field [String] The payload element to test
|
219
|
+
# @step_input regex [String] The regex to test against
|
220
|
+
Then('the {word} payload field {string} matches the regex {string}') do |request_type, field, regex_string|
|
221
|
+
regex = Regexp.new(regex_string)
|
222
|
+
list = Maze::Server.list_for(request_type)
|
223
|
+
value = Maze::Helper.read_key_path(list.current[:body], field)
|
224
|
+
Maze.check.match(regex, value)
|
225
|
+
end
|
226
|
+
|
227
|
+
# Tests a payload field is a numeric timestamp.
|
228
|
+
#
|
229
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
230
|
+
# @step_input field [String] The payload element to test
|
231
|
+
Then('the {word} payload field {string} is a parsable timestamp in seconds') do |request_type, field|
|
232
|
+
list = Maze::Server.list_for(request_type)
|
233
|
+
value = Maze::Helper.read_key_path(list.current[:body], field)
|
234
|
+
begin
|
235
|
+
int = value.to_i
|
236
|
+
parsed_time = Time.at(int)
|
237
|
+
rescue StandardError
|
238
|
+
parsed_time = nil
|
239
|
+
end
|
240
|
+
Maze.check.not_nil(parsed_time)
|
241
|
+
end
|
242
|
+
|
243
|
+
# Tests that every element in an array contains a specified key-value pair.
|
244
|
+
#
|
245
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
246
|
+
# @step_input key_path [String] The path to the tested array
|
247
|
+
# @step_input element_key_path [String] The key for the expected element inside the array
|
248
|
+
Then('each element in {word} payload field {string} has {string}') do |request_type, key_path, element_key_path|
|
249
|
+
list = Maze::Server.list_for(request_type)
|
250
|
+
value = Maze::Helper.read_key_path(list.current[:body], key_path)
|
251
|
+
Maze.check.kind_of Array, value
|
252
|
+
value.each do |element|
|
253
|
+
Maze.check.not_nil(Maze::Helper.read_key_path(element, element_key_path),
|
254
|
+
"Each element in '#{key_path}' must have '#{element_key_path}'")
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# @!group Proxy steps
|
2
|
+
|
3
|
+
# Starts an HTTP proxy server.
|
4
|
+
#
|
5
|
+
Then('I start an http proxy') do
|
6
|
+
Maze::Proxy.instance.start :Http
|
7
|
+
end
|
8
|
+
|
9
|
+
# Starts an authenticated HTTP proxy server.
|
10
|
+
#
|
11
|
+
Then('I start an authenticated http proxy') do
|
12
|
+
Maze::Proxy.instance.start :Http, true
|
13
|
+
end
|
14
|
+
|
15
|
+
# Starts an HTTPS proxy server.
|
16
|
+
#
|
17
|
+
Then('I start an https proxy') do
|
18
|
+
Maze::Proxy.instance.start :Https
|
19
|
+
end
|
20
|
+
|
21
|
+
# Starts an authenticated HTTPS proxy server.
|
22
|
+
#
|
23
|
+
Then('I start an authenticated https proxy') do
|
24
|
+
Maze::Proxy.instance.start :Https, true
|
25
|
+
end
|
26
|
+
|
27
|
+
# Test the proxy server handled a request for a host.
|
28
|
+
#
|
29
|
+
# @step_input host [String] Destination host to check
|
30
|
+
Then('the proxy handled a request for {string}') do |host|
|
31
|
+
Maze.check.true(Maze::Proxy.instance.handled_host?(host), "The proxy did not handle a request for #{host}")
|
32
|
+
end
|
33
|
+
|
34
|
+
# @!endgroup
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @!group Query parameter steps
|
4
|
+
|
5
|
+
# Tests that a query parameter matches a string.
|
6
|
+
#
|
7
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
8
|
+
# @step_input parameter_name [String] The parameter to test
|
9
|
+
# @step_input parameter_value [String] The expected value
|
10
|
+
Then('the {word} {string} query parameter equals {string}') do |request_type, parameter_name, parameter_value|
|
11
|
+
Maze.check.equal(parameter_value,
|
12
|
+
Maze::Helper.parse_querystring(Maze::Server.list_for(request_type).current)[parameter_name][0])
|
13
|
+
end
|
14
|
+
|
15
|
+
# Tests that a query parameter is present and not null.
|
16
|
+
#
|
17
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
18
|
+
# @step_input parameter_name [String] The parameter to test
|
19
|
+
Then('the {word} {string} query parameter is not null') do |request_type, parameter_name|
|
20
|
+
Maze.check.not_nil(Maze::Helper.parse_querystring(Maze::Server.list_for(request_type).current)[parameter_name][0],
|
21
|
+
"The '#{parameter_name}' query parameter should not be null")
|
22
|
+
end
|
23
|
+
|
24
|
+
# Tests that a query parameter is a timestamp.
|
25
|
+
#
|
26
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
27
|
+
# @step_input parameter_name [String] The parameter to test
|
28
|
+
Then('the {word} {string} query parameter is a timestamp') do |request_type, parameter_name|
|
29
|
+
param = Maze::Helper.parse_querystring(Maze::Server.list_for(request_type).current)[parameter_name][0]
|
30
|
+
Maze.check.match(TIMESTAMP_REGEX, param)
|
31
|
+
end
|