bugsnag-maze-runner 7.22.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/bin/bugsnag-print-load-paths +6 -0
  3. data/bin/download-logs +74 -0
  4. data/bin/maze-runner +174 -0
  5. data/bin/upload-app +56 -0
  6. data/lib/features/scripts/await-android-emulator.sh +11 -0
  7. data/lib/features/scripts/clear-android-app-data.sh +8 -0
  8. data/lib/features/scripts/force-stop-android-app.sh +8 -0
  9. data/lib/features/scripts/install-android-app.sh +15 -0
  10. data/lib/features/scripts/launch-android-app.sh +38 -0
  11. data/lib/features/scripts/launch-android-emulator.sh +15 -0
  12. data/lib/features/steps/android_steps.rb +51 -0
  13. data/lib/features/steps/app_automator_steps.rb +228 -0
  14. data/lib/features/steps/aws_sam_steps.rb +212 -0
  15. data/lib/features/steps/breadcrumb_steps.rb +80 -0
  16. data/lib/features/steps/browser_steps.rb +93 -0
  17. data/lib/features/steps/build_api_steps.rb +25 -0
  18. data/lib/features/steps/document_server_steps.rb +7 -0
  19. data/lib/features/steps/error_reporting_steps.rb +358 -0
  20. data/lib/features/steps/feature_flag_steps.rb +190 -0
  21. data/lib/features/steps/header_steps.rb +72 -0
  22. data/lib/features/steps/log_steps.rb +29 -0
  23. data/lib/features/steps/multipart_request_steps.rb +142 -0
  24. data/lib/features/steps/network_steps.rb +135 -0
  25. data/lib/features/steps/payload_steps.rb +257 -0
  26. data/lib/features/steps/proxy_steps.rb +34 -0
  27. data/lib/features/steps/query_parameter_steps.rb +31 -0
  28. data/lib/features/steps/request_assertion_steps.rb +186 -0
  29. data/lib/features/steps/runner_steps.rb +428 -0
  30. data/lib/features/steps/session_tracking_steps.rb +116 -0
  31. data/lib/features/steps/trace_steps.rb +206 -0
  32. data/lib/features/steps/value_steps.rb +119 -0
  33. data/lib/features/support/env.rb +7 -0
  34. data/lib/features/support/internal_hooks.rb +207 -0
  35. data/lib/maze/api/appium/file_manager.rb +29 -0
  36. data/lib/maze/appium_server.rb +112 -0
  37. data/lib/maze/assertions/request_set_assertions.rb +97 -0
  38. data/lib/maze/aws/sam.rb +112 -0
  39. data/lib/maze/aws_public_ip.rb +53 -0
  40. data/lib/maze/bugsnag_config.rb +42 -0
  41. data/lib/maze/checks/assert_check.rb +69 -0
  42. data/lib/maze/checks/noop_check.rb +34 -0
  43. data/lib/maze/client/appium/base_client.rb +131 -0
  44. data/lib/maze/client/appium/bb_client.rb +102 -0
  45. data/lib/maze/client/appium/bb_devices.rb +127 -0
  46. data/lib/maze/client/appium/bs_client.rb +91 -0
  47. data/lib/maze/client/appium/bs_devices.rb +141 -0
  48. data/lib/maze/client/appium/bs_legacy_client.rb +31 -0
  49. data/lib/maze/client/appium/local_client.rb +67 -0
  50. data/lib/maze/client/appium.rb +23 -0
  51. data/lib/maze/client/bb_api_client.rb +102 -0
  52. data/lib/maze/client/bb_client_utils.rb +181 -0
  53. data/lib/maze/client/bs_client_utils.rb +168 -0
  54. data/lib/maze/client/selenium/base_client.rb +15 -0
  55. data/lib/maze/client/selenium/bb_browsers.yml +188 -0
  56. data/lib/maze/client/selenium/bb_client.rb +38 -0
  57. data/lib/maze/client/selenium/bs_browsers.yml +257 -0
  58. data/lib/maze/client/selenium/bs_client.rb +89 -0
  59. data/lib/maze/client/selenium/local_client.rb +16 -0
  60. data/lib/maze/client/selenium.rb +16 -0
  61. data/lib/maze/compare.rb +161 -0
  62. data/lib/maze/configuration.rb +182 -0
  63. data/lib/maze/docker.rb +147 -0
  64. data/lib/maze/document_server.rb +46 -0
  65. data/lib/maze/driver/appium.rb +198 -0
  66. data/lib/maze/driver/browser.rb +124 -0
  67. data/lib/maze/errors.rb +52 -0
  68. data/lib/maze/generator.rb +55 -0
  69. data/lib/maze/helper.rb +122 -0
  70. data/lib/maze/hooks/appium_hooks.rb +55 -0
  71. data/lib/maze/hooks/browser_hooks.rb +15 -0
  72. data/lib/maze/hooks/command_hooks.rb +9 -0
  73. data/lib/maze/hooks/error_code_hook.rb +49 -0
  74. data/lib/maze/hooks/hooks.rb +61 -0
  75. data/lib/maze/http_request.rb +21 -0
  76. data/lib/maze/interactive_cli.rb +173 -0
  77. data/lib/maze/logger.rb +86 -0
  78. data/lib/maze/macos_utils.rb +14 -0
  79. data/lib/maze/maze_output.rb +88 -0
  80. data/lib/maze/network.rb +49 -0
  81. data/lib/maze/option/parser.rb +240 -0
  82. data/lib/maze/option/processor.rb +130 -0
  83. data/lib/maze/option/validator.rb +155 -0
  84. data/lib/maze/option.rb +62 -0
  85. data/lib/maze/plugins/bugsnag_reporting_plugin.rb +49 -0
  86. data/lib/maze/plugins/cucumber_report_plugin.rb +101 -0
  87. data/lib/maze/plugins/error_code_plugin.rb +21 -0
  88. data/lib/maze/plugins/global_retry_plugin.rb +38 -0
  89. data/lib/maze/proxy.rb +114 -0
  90. data/lib/maze/request_list.rb +87 -0
  91. data/lib/maze/request_repeater.rb +49 -0
  92. data/lib/maze/retry_handler.rb +67 -0
  93. data/lib/maze/runner.rb +149 -0
  94. data/lib/maze/schemas/OtelTraceSchema.json +390 -0
  95. data/lib/maze/schemas/trace_schema.rb +7 -0
  96. data/lib/maze/schemas/trace_validator.rb +98 -0
  97. data/lib/maze/server.rb +251 -0
  98. data/lib/maze/servlets/base_servlet.rb +27 -0
  99. data/lib/maze/servlets/command_servlet.rb +47 -0
  100. data/lib/maze/servlets/log_servlet.rb +64 -0
  101. data/lib/maze/servlets/reflective_servlet.rb +70 -0
  102. data/lib/maze/servlets/servlet.rb +199 -0
  103. data/lib/maze/servlets/temp.rb +0 -0
  104. data/lib/maze/servlets/trace_servlet.rb +13 -0
  105. data/lib/maze/store.rb +15 -0
  106. data/lib/maze/terminating_server.rb +129 -0
  107. data/lib/maze/timers.rb +51 -0
  108. data/lib/maze/wait.rb +35 -0
  109. data/lib/maze.rb +27 -0
  110. data/lib/utils/deep_merge.rb +17 -0
  111. data/lib/utils/selenium_money_patch.rb +17 -0
  112. 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