Module: Bitfab::MockOverride
- Defined in:
- lib/bitfab/mock_override.rb
Overview
Selective mock overrides for replay. Mirrors the TypeScript SDK's mockOverride feature.
A mock override injects a custom value into a specific span (node) during replay: the matched span short-circuits its real execution and returns the value the processor produces, so downstream real code runs against the substituted output. This is a third mock mode alongside "run real code" and "replay recorded output" (see MOCK_STRATEGIES in replay.rb).
An override is a (match, value) pair, represented as a symbol-keyed hash { match:, value: }:
-
match is a callable (proc/lambda): match.call(node) -> boolean. node is a structural-metadata hash { trace_function_key:, span_name:, type:, original_span_id: } (symbol keys; original_span_id may be nil when the live span has no recorded counterpart). Matching must not depend on the recorded output.
-
value is EITHER a flat value OR a callable. A flat value is injected directly (e.g. value: { label: "refund" }). A callable is invoked with the ctx hash: value.call(ctx) where ctx is { node:, inputs:, kwargs:, get_original_output: } - inputs is the live replay positional args array, kwargs is the live keyword args hash (empty when the call used none), and get_original_output is a proc returning this span's recorded output (deserialized; raises if there is no recorded counterpart). Either way the resulting value IS the span's output (full replacement, no merge); nil is a legitimate injected value. To inject a proc as the literal output, wrap it in a callable value: value: ->(ctx) { the_proc }.
Unlike the TypeScript SDK, Ruby's span tree is fetched with outputs inline (get_span_tree), so get_original_output simply returns the inline recorded output. There is no lazy per-span fetch and Ruby is synchronous, so there is no async limitation.
Class Method Summary collapse
-
.normalize(mock_override) ⇒ Array<Hash>
Normalize the per-call
mock_overrideoption (a single override hash, an array of them, or nil) into an array.
Class Method Details
.normalize(mock_override) ⇒ Array<Hash>
Normalize the per-call mock_override option (a single override hash, an
array of them, or nil) into an array. First match wins downstream, so
order is preserved.
Each override is validated: it must be a hash with a callable :match and
must include a :value key. A forgotten :value raises rather than
silently short-circuiting matched spans with nil (an explicit value: nil
is a legitimate injected value and passes). Mirrors the guard on
register_mock_override, and the Python/TypeScript SDKs, where the per-call
override object requires a value.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/bitfab/mock_override.rb', line 54 def normalize(mock_override) return [] if mock_override.nil? overrides = mock_override.is_a?(Array) ? mock_override : [mock_override] overrides.each do |override| unless override.is_a?(Hash) && override[:match].respond_to?(:call) raise ArgumentError, "mock_override requires a callable :match. Pass a " \ "{ match:, value: } hash (or an array of them). value may be a " \ "flat value or a callable." end unless override.key?(:value) raise ArgumentError, "mock_override requires a :value (a flat value or a callable); " \ "pass value: nil explicitly to inject nil." end end overrides end |