Class: RightDevelop::Testing::Recording::Metadata
- Inherits:
-
Object
- Object
- RightDevelop::Testing::Recording::Metadata
- Defined in:
- lib/right_develop/testing/recording/metadata.rb
Overview
Metadata for record and playback.
Defined Under Namespace
Classes: MissingVariableFailure, RecordingError, RetryableFailure
Constant Summary collapse
- HIDDEN_CREDENTIAL_VALUE =
value used for obfuscation.
'HIDDEN_CREDENTIAL'.freeze
- VERBS =
common API verbs.
%w(DELETE GET HEAD PATCH POST PUT).freeze
- MODES =
valid modes, determines how variables are substituted, etc.
%w(echo record playback)
- KINDS =
valid kinds, also keys under matchers.
%w(request response)
- MATCHERS_KEY =
route-relative config keys.
'matchers'.freeze
- SIGNIFICANT_KEY =
'significant'.freeze
- TIMEOUTS_KEY =
'timeouts'.freeze
- TRANSFORM_KEY =
'transform'.freeze
- VARIABLES_KEY =
'variables'.freeze
- VARIABLE_INDEX_REGEX =
finds the value index for a recorded variable, if any.
/\[(\d+)\]$/- HALT =
throw/catch signals.
:halt_recording_metadata_generator
Instance Attribute Summary collapse
-
#body ⇒ Object
readonly
Returns the value of attribute body.
-
#effective_route_config ⇒ Object
readonly
Returns the value of attribute effective_route_config.
-
#headers ⇒ Object
readonly
Returns the value of attribute headers.
-
#http_status ⇒ Object
readonly
Returns the value of attribute http_status.
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#mode ⇒ Object
readonly
Returns the value of attribute mode.
-
#uri ⇒ Object
readonly
Returns the value of attribute uri.
-
#variables ⇒ Object
readonly
Returns the value of attribute variables.
-
#verb ⇒ Object
readonly
Returns the value of attribute verb.
Class Method Summary collapse
-
.deep_sorted_data(data) ⇒ String
Duplicates and sorts hash keys for a consistent appearance (in JSON).
-
.deep_sorted_json(data, pretty = false) ⇒ String
Sorts data for a consistent appearance in JSON.
-
.normalize_header_key(key) ⇒ String
Establishes a normal header key form for agreement between configuration and metadata pieces.
-
.normalize_uri(url) ⇒ URI
Uri with scheme inserted if necessary.
Instance Method Summary collapse
-
#checksum ⇒ String
Computed checksum for normalized ‘significant’ data.
-
#initialize(options) ⇒ Metadata
constructor
Computes the metadata used to identify where the request/response should be stored-to/retrieved-from.
-
#query ⇒ String
Normalized query string.
-
#timeouts ⇒ Hash
Timeouts from effective configuration or empty.
Constructor Details
#initialize(options) ⇒ Metadata
Computes the metadata used to identify where the request/response should be stored-to/retrieved-from. Recording the full request is not strictly necessary (because the request maps to a MD5 used for response-only) but it adds human-readability and the ability to manually customize some or all responses.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 96 def initialize() unless (@logger = [:logger]) raise ::ArgumentError, "options[:logger] is required: #{@logger.inspect}" end unless (@mode = [:mode].to_s) && MODES.include?(@mode) raise ::ArgumentError, "options[:mode] must be one of #{MODES.inspect}: #{@mode.inspect}" end unless (@kind = [:kind].to_s) && KINDS.include?(@kind) raise ::ArgumentError, "options[:kind] must be one of #{KINDS.inspect}: #{@kind.inspect}" end unless (@uri = [:uri]) && @uri.respond_to?(:path) raise ::ArgumentError, "options[:uri] must be a valid parsed URI: #{@uri.inspect}" end unless (@verb = [:verb]) && VERBS.include?(@verb) raise ::ArgumentError, "options[:verb] must be one of #{VERBS.inspect}: #{@verb.inspect}" end unless (@headers = [:headers]).kind_of?(::Hash) raise ::ArgumentError, "options[:headers] must be a hash: #{@headers.inspect}" end unless (@route_data = [:route_data]).kind_of?(::Hash) raise ::ArgumentError, "options[:route_data] must be a hash: #{@route_data.inspect}" end @http_status = [:http_status] if @kind == 'response' @http_status = Integer(@http_status) elsif !@http_status.nil? raise ::ArgumentError, "options[:http_status] is unexpected for #{@kind}." end unless (@variables = [:variables]).kind_of?(::Hash) raise ::ArgumentError, "options[:variables] must be a hash: #{@variables.inspect}" end if (@effective_route_config = [:effective_route_config]) && !@effective_route_config.kind_of?(::Hash) raise ::ArgumentError, "options[:effective_route_config] is not a hash: #{@effective_route_config.inspect}" end @body = [:body] # not required # merge one or more wildcard configurations matching the current uri and # parameters. @headers = normalize_headers(@headers) @typenames_to_values = compute_typenames_to_values # effective route config may already have been computed for request # (on record) or not (on playback). @effective_route_config ||= compute_effective_route_config # apply the configuration by substituting for variables in the request and # by obfuscating wherever a variable name is nil. case @mode when 'echo' # do nothing; used to validate the fixtures before playback, etc. else erck = @effective_route_config[@kind] if effective_variables = erck && erck[VARIABLES_KEY] recursive_replace_variables( [@kind, VARIABLES_KEY], @typenames_to_values, effective_variables, erck[TRANSFORM_KEY]) end if logger.debug? logger.debug("#{@kind} effective_route_config = #{@effective_route_config[@kind].inspect}") logger.debug("#{@kind} typenames_to_values = #{@typenames_to_values.inspect}") end end # recreate headers and body from data using variable substitutions and # obfuscations. @headers = @typenames_to_values[:header] @body = normalize_body(@headers, @typenames_to_values[:body] || @body) end |
Instance Attribute Details
#body ⇒ Object (readonly)
Returns the value of attribute body.
88 89 90 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 88 def body @body end |
#effective_route_config ⇒ Object (readonly)
Returns the value of attribute effective_route_config.
89 90 91 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 89 def effective_route_config @effective_route_config end |
#headers ⇒ Object (readonly)
Returns the value of attribute headers.
88 89 90 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 88 def headers @headers end |
#http_status ⇒ Object (readonly)
Returns the value of attribute http_status.
88 89 90 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 88 def http_status @http_status end |
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
89 90 91 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 89 def logger @logger end |
#mode ⇒ Object (readonly)
Returns the value of attribute mode.
89 90 91 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 89 def mode @mode end |
#uri ⇒ Object (readonly)
Returns the value of attribute uri.
88 89 90 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 88 def uri @uri end |
#variables ⇒ Object (readonly)
Returns the value of attribute variables.
89 90 91 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 89 def variables @variables end |
#verb ⇒ Object (readonly)
Returns the value of attribute verb.
88 89 90 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 88 def verb @verb end |
Class Method Details
.deep_sorted_data(data) ⇒ String
Duplicates and sorts hash keys for a consistent appearance (in JSON). Traverses arrays to sort hash elements. Note this only works for Ruby 1.9+ due to hashes now preserving insertion order.
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 243 def self.deep_sorted_data(data) case data when ::Hash data = data.map { |k, v| [k.to_s, v] }.sort.inject({}) do |h, (k, v)| h[k] = deep_sorted_data(v) h end when Array data.map { |e| deep_sorted_data(e) } else if data.respond_to?(:to_hash) deep_sorted_data(data.to_hash) else data end end end |
.deep_sorted_json(data, pretty = false) ⇒ String
Sorts data for a consistent appearance in JSON.
HACK: replacement for ::RightSupport::Data::HashTools.deep_sorted_json method that can underflow the @state.depth field as -1 probably due to some (1.9.3+?) logic that resets the depth to zero when JSON data gets too deep or else @state.depth doesn’t mean what it used to mean in Ruby 1.8. need to fix the utility…
231 232 233 234 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 231 def self.deep_sorted_json(data, pretty = false) data = deep_sorted_data(data) pretty ? ::JSON.pretty_generate(data) : ::JSON.dump(data) end |
.normalize_header_key(key) ⇒ String
Establishes a normal header key form for agreement between configuration and metadata pieces.
193 194 195 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 193 def self.normalize_header_key(key) key.to_s.downcase.gsub('-', '_') end |
.normalize_uri(url) ⇒ URI
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 200 def self.normalize_uri(url) # the following logic is borrowed from RestClient::Request#parse_url url = "http://#{url}" unless url.match(/^http/) uri = ::URI.parse(url) # need at least a (leading) forward-slash in path for any subsequent route # matching. uri.path = '/' if uri.path.empty? # strip proxied server details not needed for playback. # strip any basic authentication, which is never recorded. uri = ::URI.parse(url) uri.scheme = nil uri.host = nil uri.port = nil uri.user = nil uri.password = nil uri end |
Instance Method Details
#checksum ⇒ String
178 179 180 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 178 def checksum @checksum ||= compute_checksum end |
#query ⇒ String
168 169 170 171 172 173 174 175 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 168 def query q = @typenames_to_values[:query] if q && !q.empty? build_query_string(q) else nil end end |
#timeouts ⇒ Hash
183 184 185 |
# File 'lib/right_develop/testing/recording/metadata.rb', line 183 def timeouts (@effective_route_config[@kind] || {})[TIMEOUTS_KEY] || {} end |