Class ScenarioRuntime

java.lang.Object
io.karatelabs.core.ScenarioRuntime
All Implemented Interfaces:
KarateJsContext, Callable<ScenarioResult>

public class ScenarioRuntime extends Object implements Callable<ScenarioResult>, KarateJsContext
  • Constructor Details

    • ScenarioRuntime

      public ScenarioRuntime(FeatureRuntime featureRuntime, Scenario scenario)
    • ScenarioRuntime

      public ScenarioRuntime(KarateJs karate, Scenario scenario)
      Constructor for standalone execution without FeatureRuntime.
  • Method Details

    • currentOrNull

      public static ScenarioRuntime currentOrNull()
      The scenario executing on the current thread, or null outside a scenario's call().
    • isReportDisabled

      public boolean isReportDisabled()
    • getConfigVars

      public Map<String,Object> getConfigVars()
      The merged config-phase variables (base + config + env), populated during init when config is evaluated (a top-level scenario); empty otherwise. Used by ConfigLoader.configOnly.
    • getInheritedVariables

      public Map<String,Object> getInheritedVariables()
    • getAssignedVariables

      public Set<String> getAssignedVariables()
    • executeSetup

      public Map<String,Object> executeSetup(String name)
      Execute the @setup scenario and return all its variables.
    • executeSetupOnce

      public Map<String,Object> executeSetupOnce(String name)
      Execute the @setup scenario with caching (only runs once per feature).
    • executeJsCall

      public Object executeJsCall(String path, Object arg)
      Execute a feature via karate.call() and return its result variables. This is used for JavaScript calls like: karate.call('other.feature', { arg: 'value' }) Supports call-by-tag syntax: - call('file.feature@name=tagvalue') - call feature, run only scenario with matching tag - call('@tagname') - call scenario in same file by tag When arg is a List, loops over elements (same as `call read('path') array`) and returns a List of result maps.
    • executeJsCallOnce

      public Object executeJsCallOnce(String path, Object arg)
      Execute karate.callonce() - runs a feature once per FeatureRuntime and caches the result. Uses the same cache as the callonce keyword. Uses double-check locking to ensure thread-safe execution in parallel scenarios.
    • executeCallSingle

      public Object executeCallSingle(String path, Object arg)
      Execute karate.callSingle() - runs a file once per Suite and caches the result. Uses Suite-level locking to ensure thread-safe execution in parallel scenarios. Flow: 1. Check in-memory cache (lock-free for fast path) 2. If callSingleCache is configured, check disk cache 3. If not cached, acquire Suite lock 4. Double-check cache (another thread may have cached while waiting) 5. Execute and cache result (in-memory and optionally to disk) 6. Return deep copy to prevent cross-thread mutation Disk caching (configure callSingleCache): - { minutes: 15 } - cache to disk for 15 minutes (default dir: karate-temp/cache) - { minutes: 15, dir: 'some/folder' } - custom cache directory - Only JSON-like results (Map/List) are persisted to disk Exceptions are cached and re-thrown on subsequent calls.
    • call

      public ScenarioResult call()
      Specified by:
      call in interface Callable<ScenarioResult>
    • eval

      public Object eval(String expression)
    • eval

      public Object eval(String expression, Step step)
      Evaluate a JS expression with debug source information from a Gherkin step. Creates an embedded Resource so the JS engine's debug points carry the feature file path and correct line numbers.
      Parameters:
      expression - the JS expression text
      step - the Gherkin step that contains this expression
    • evalAsStep

      public StepResult evalAsStep(String text)
      Evaluate text as a Gherkin step against this runtime's variable / HTTP state. Accepts any Karate step prefix (*, Given, When, Then, And, But) and prepends "* " when no prefix is present, so a plain expression like "myFunc('input')" works too. The synthesized step is marked fake (Step.isFake()) so listener and interceptor callbacks are skipped.
    • evalDocString

      public Object evalDocString(String expression, Step step)
      Evaluate a JS docstring expression with debug source information. Uses the docstring's actual content start line for precise line mapping.
    • setVariable

      public void setVariable(String name, Object value)
    • setHiddenVariable

      public void setHiddenVariable(String name, Object value)
      Set a "hidden" variable that is accessible in JS but excluded from getAllVariables(). Used for internal implementation details like responseBytes, responseType, etc.
    • getVariable

      public Object getVariable(String name)
    • getAllVariables

      public Map<String,Object> getAllVariables()
    • getEngine

      public io.karatelabs.js.Engine getEngine()
    • getHttp

      public HttpRequestBuilder getHttp()
    • getKarate

      public KarateJs getKarate()
    • isRequestExpressionsEnabled

      public boolean isRequestExpressionsEnabled()
      Whether a mock should evaluate embedded expressions found in request-derived data. Off by default (request data is treated as inert data); a mock can opt in via the MockServer.Builder flag or configure requestExpressionsEnabled = true.
    • setRequestExpressionsEnabled

      public void setRequestExpressionsEnabled(boolean requestExpressionsEnabled)
    • clearRequestDerived

      public void clearRequestDerived()
      Forget all request-derived values; called by the Mock Server at the start of each request.
    • recordFailedEmbedded

      public void recordFailedEmbedded(String placeholder, Exception error)
      An embedded expression that was evaluated and threw, keyed by the placeholder text it was left as. StepExecutor preserves such a placeholder deliberately (the schema-as-template pattern lets the match engine retry it later with the right context) — but a consumer that emits the value instead of matching it never gets that second chance, and the placeholder becomes data.

      The record is kept here, at the failure, rather than re-derived by inspecting a value later, because the two are not the same question. A #(...) string in a finished value may be a failed expression, or it may be text that was never an expression at all — echoed request data, or the output of some other expression. Only this side knows which.

    • failedEmbedded

      public Exception failedEmbedded(String placeholder)
      The error a surviving placeholder failed with, or null if it was never evaluated at all.
    • hasFailedEmbedded

      public boolean hasFailedEmbedded()
      True if any embedded expression was evaluated and threw since the last clear.
    • failedEmbeddedKeys

      public Set<String> failedEmbeddedKeys()
      The placeholders recorded as failed — for a consumer whose value is text rather than a tree.
    • markRequestDerived

      public void markRequestDerived(Object value)
      Deep-mark a value (and every nested Map/List) as having originated from an untrusted HTTP request, so processEmbeddedExpressions will leave its #(...) strings inert. Containers are marked by identity; strings that carry an embedded expression are also remembered by value, so they stay inert after a step extracts them out of the container.
    • isRequestDerived

      public boolean isRequestDerived(Object value)
      True if the value was marked by markRequestDerived(java.lang.Object). Free when nothing is marked.
    • getCookieJar

      public Map<String,Map<String,Object>> getCookieJar()
      Get the cookie jar for auto-sending cookies on subsequent requests. Returns a map of cookie name to cookie details (value, path, domain, etc.).
    • updateCookieJar

      public void updateCookieJar(Object responseCookies)
      Add cookies from responseCookies to the cookie jar for auto-send. Called after each HTTP response to persist cookies.
    • clearCookieJar

      public void clearCookieJar()
      Clear the cookie jar (for clearCookies functionality).
    • configure

      public void configure(String key, Object value)
    • getRuntime

      public ScenarioRuntime getRuntime()
      Description copied from interface: KarateJsContext
      Returns the ScenarioRuntime, or null for standalone usage.
      Specified by:
      getRuntime in interface KarateJsContext
    • getConfig

      public KarateConfig getConfig()
      Description copied from interface: KarateJsContext
      Returns the runtime configuration.
      Specified by:
      getConfig in interface KarateJsContext
    • getExecutor

      public StepExecutor getExecutor()
    • getWorkingDir

      public io.karatelabs.common.Resource getWorkingDir()
      Description copied from interface: KarateJsContext
      Returns the working directory resource for resolving relative paths.
      Specified by:
      getWorkingDir in interface KarateJsContext
    • getScenario

      public Scenario getScenario()
    • getFeatureRuntime

      public FeatureRuntime getFeatureRuntime()
    • getResult

      public ScenarioResult getResult()
    • getCurrentStep

      public Step getCurrentStep()
    • isStopped

      public boolean isStopped()
    • isAborted

      public boolean isAborted()
    • getError

      public Throwable getError()
    • abort

      public void abort()
    • stop

      public void stop()
    • hotReload

      public boolean hotReload()
      Re-reads the feature from disk and updates step text in place for any steps whose text changed. Returns true if at least one step was updated.
    • stepBack

      public void stepBack()
      Move execution back one step (for debugging). After calling this, the previous step will be re-executed.
    • stepReset

      public void stepReset()
      Reset to re-execute the current step (for debugging after hot reload).
    • stepProceed

      public void stepProceed()
      Continue execution from current position (after a pause).
    • getStepIndex

      public int getStepIndex()
      Get current step index for debugging.
    • getStepCount

      public int getStepCount()
      Get total number of steps.
    • setDebugSupport

      public <T> void setDebugSupport(io.karatelabs.js.RunInterceptor<T> interceptor, io.karatelabs.js.DebugPointFactory<T> factory)
    • getInterceptor

      public io.karatelabs.js.RunInterceptor<?> getInterceptor()
    • getPointFactory

      public io.karatelabs.js.DebugPointFactory<?> getPointFactory()
    • setSkipBackground

      public void setSkipBackground(boolean skipBackground)
    • isSkipBackground

      public boolean isSkipBackground()
    • getDriver

      public Driver getDriver()
      Get the browser driver, initializing it lazily if needed. Requires driver to be configured via `configure driver = { ... }`.
      Returns:
      the Driver instance
      Throws:
      RuntimeException - if driver is not configured
    • registerChannel

      public void registerChannel(Channel channel)
      Register a channel for lifecycle management. Called by karate.channel(). The channel's afterScenario() will be called when the scenario ends.
    • getDriverIfPresent

      public Driver getDriverIfPresent()
      Get the driver without initializing it. Returns null if driver has not been initialized. Used for checking if driver exists without side effects.
    • getDriverScope

      public String getDriverScope()
      Get the driver scope ("scenario" or "caller").
    • isCallerScope

      public boolean isCallerScope()
      Check if driver scope is "caller" (V1-style propagation).
    • setDriverFromCallee

      public void setDriverFromCallee(ScenarioRuntime callee)
      Set driver from a callee feature (upward propagation). When callee has scope: "caller", driver propagates to the caller so it can be used after the call returns.
    • setListenResult

      public void setListenResult(Object result)
      Set the listen result (called by karate.signal()). Triggers any waiting listen() call to complete.
    • waitForListenResult

      public Object waitForListenResult(long timeoutMs)
      Wait for a signal with timeout. Returns the signaled result or throws on timeout.
    • getListenResult

      public Object getListenResult()
      Get the current listen result without waiting.
    • isPerfMode

      public boolean isPerfMode()
      Check if performance mode is enabled. When true, HTTP request timing is reported via PerfHook.
    • getPerfHook

      public PerfHook getPerfHook()
      Get the PerfHook for reporting performance events.
      Returns:
      the PerfHook or null if not in perf mode
    • capturePerfEvent

      public void capturePerfEvent(PerfEvent event)
      Capture a performance event for the HTTP request just completed.

      This implements the "deferred reporting" pattern from v1: - The previous event is reported first (if any) - The new event is held until the next HTTP request or scenario end - This allows assertion failures to be attributed to the preceding HTTP request

      Parameters:
      event - the performance event to capture
    • logLastPerfEvent

      public boolean logLastPerfEvent(String failureMessage)
      Log (report) the last captured performance event.

      Called: 1. Before each new HTTP request (to report the previous one) 2. At scenario end (to report the final request, with any failure message)

      If failureMessage is non-null, the event is marked as failed.

      Parameters:
      failureMessage - the failure message (null if successful)
      Returns:
      true if a failed event was reported — i.e. the failure was carried by a real HTTP perf event. False if there was no held event or it was reported as OK. The caller uses this to decide whether a scenario failure still needs a synthetic perf event (a failure before the first HTTP request would otherwise vanish).
    • captureCustomPerfEvent

      public void captureCustomPerfEvent(String name, long startTime, long endTime)
      Capture a custom performance event (for non-HTTP operations like DB, gRPC).

      Unlike HTTP events, custom events are reported immediately.

      Parameters:
      name - the event name
      startTime - start time in epoch milliseconds
      endTime - end time in epoch milliseconds