Package io.karatelabs.core
Class StepUtils
java.lang.Object
io.karatelabs.core.StepUtils
Static utility methods for step execution.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordThe callable target and (optional) argument expression of a call step, e.g.static final recordParsed result of a feature path with optional tag selector or line filter.static final class -
Method Summary
Modifier and TypeMethodDescriptionThe bindings a called feature actually added or replaced — its contribution minus the caller state it merely inherited.calleeDelta(Map<String, Object> callerVars, Map<String, Object> calleeVars, Set<String> assignedNames) static booleanTrue when an LHS path uses a JsonPath construct that JS can't evaluate:[*](array wildcard),..(recursive descent), or[?(...)](filter).static ObjectDeep copy a value (Map, List, or primitive).static intfindAssignmentOperator(String text) Find the first '=' that's an assignment operator (not ==, !static intfindReadCloseParen(String text) Find the index of the `)` that matches the leading `read(` intext, skipping anything inside single- or double-quoted strings and tracking nested parens.static ObjectgetOrCreatePath(Map<String, Object> target, String path) Navigate to or create a nested path in a map structure.static booleanCheck if string contains JS expression punctuation like . ( [ ] ' "static booleanisLiteralFeatureRead(String text) Check if text is a literal feature file read like read('file.feature').static booleanTrue ifsis a bare identifier — letter/_/$ followed by letters/digits/_/$.static booleanisPureJsonPath(String lhs) True iflhsis a "pure" JSON path expression: an identifier followed by zero or more path segments where every segment is one of.ident,[int],[int:int],['str'],["str"],[*],..,[?(...)].static booleanisValidVariableName(String name) Check if a string is a valid Karate variable name.static StepUtils.ParsedFeaturePathparseFeaturePath(String rawPath) Parse a feature path into path and tag/line components.static voidremoveAtPath(Map<String, Object> map, String path) Remove a value at a nested path in a map.static voidsetValueAtPath(Object target, String path, Object value) Set a value at a nested path, handling both dot notation and array brackets.static StepUtils.CallPartssplitCallExpr(String text) Split a call expression into its callable target and argument, mirroring v1'sparseCallArgs.static StepUtils.VarAndPathSplit an LHS likebody[*].parentinto variablebodyand JsonPath$[*].parent.static StringConvert a value to its string representation
-
Method Details
-
parseFeaturePath
Parse a feature path into path and tag/line components. Supports: - file.feature@tag - call specific scenario by tag - file.feature:10 / file.feature:10:25 - call by line number(s); matches Runner.path(...) suite-side syntax. Tag and line are mutually exclusive on the same path; tag suffix wins by parse order. - @tag - call scenario in same file by tag - file.feature - normal call without tag- Parameters:
rawPath- the raw path string (may contain @tag or :N suffix)- Returns:
- ParsedFeaturePath with separated path and selector components
-
isValidVariableName
Check if a string is a valid Karate variable name. Must start with letter or underscore, followed by letters, digits, or underscores. -
findReadCloseParen
Find the index of the `)` that matches the leading `read(` intext, skipping anything inside single- or double-quoted strings and tracking nested parens. Returns -1 iftextdoes not start withread(or no matching paren is found. Used to safely splitread(path) argeven when the path contains characters like)inside quotes. -
splitCallExpr
Split a call expression into its callable target and argument, mirroring v1'sparseCallArgs. For aread(...)expression the split is at read()'s close paren, so the argument may be either space-separated (read('x') arg) or directly appended (read('x.js')(arg)— the V1 immediately-invoke form). Otherwise the split is at the first space. -
isLiteralFeatureRead
Check if text is a literal feature file read like read('file.feature'). -
calleeDelta
public static Map<String,Object> calleeDelta(Map<String, Object> callerVars, Map<String, Object> calleeVars) The bindings a called feature actually added or replaced — its contribution minus the caller state it merely inherited. A called feature runs with the caller's visible variables in scope, socalleeVarsechoes them back; caching that full set leaks caller state into a shared cache (Scenario Outline example-row columns frozen to the first row, config-levelJava.type(...)refs, etc.). Shared by thecallonceandcallSinglecaches so both isolate the callee's delta the same way.Identity comparison is intentional: an untouched inherited binding keeps the same Object reference, while a callee
def/assign produces a new one — so a key absent from the caller, or present but pointing at a different object, is part of the delta.Identity alone is not enough, though: a callee that assigns the very object it was handed (
* def x = seed, where the caller passed its ownxin asseed) leaves the binding identity-equal to the inherited one, so its owndefvanished from the result.assignedNamescarries the names the callee bound for itself (ScenarioRuntime.getAssignedVariables()) and is unioned in. The two rules only ever add to the delta; an inherited binding the callee never touched still stays out. -
calleeDelta
-
deepCopy
Deep copy a value (Map, List, or primitive). -
getOrCreatePath
Navigate to or create a nested path in a map structure. Creates intermediate maps as needed. -
setValueAtPath
Set a value at a nested path, handling both dot notation and array brackets. -
removeAtPath
Remove a value at a nested path in a map. -
findAssignmentOperator
Find the first '=' that's an assignment operator (not ==, !=, invalid input: '<'=, >=).- Parameters:
text- the text to search- Returns:
- index of '=' or -1 if not found
-
hasPunctuation
Check if string contains JS expression punctuation like . ( [ ] ' "- Parameters:
s- the string to check- Returns:
- true if contains punctuation
-
stringify
Convert a value to its string representation. - null -> "null" - String -> as-is - Map/List -> JSON - Node -> XML - Other -> toString()- Parameters:
value- the value to stringify- Returns:
- string representation
-
containsJsonPathWildcard
True when an LHS path uses a JsonPath construct that JS can't evaluate:[*](array wildcard),..(recursive descent), or[?(...)](filter). Used by `set` / `remove` to fall back to Jayway when a step likeset body[*].parent = 'test'would otherwise hit the JS parser. -
isPlainIdentifier
True ifsis a bare identifier — letter/_/$ followed by letters/digits/_/$. Used by `set` to distinguish full-replacement (`set foo = ...`) from path/JS forms (`set foo.b = ...`, `set arr[0] = ...`). -
isPureJsonPath
True iflhsis a "pure" JSON path expression: an identifier followed by zero or more path segments where every segment is one of.ident,[int],[int:int],['str'],["str"],[*],..,[?(...)]. JS-style dynamic indices (e.g.[i],[i+1]) deliberately fail this check so they continue to route through the JS engine. Used by `set` / `remove` to route LHS paths through Jayway, which mirrors v1 semantics — most importantly, auto-vivifying intermediate objects when the target path doesn't yet exist. -
splitVarAndJsonPath
Split an LHS likebody[*].parentinto variablebodyand JsonPath$[*].parent. Mirrors v1'sparseVariableAndPath: variable is the leading identifier ([A-Za-z_$][A-Za-z0-9_$]*); the rest becomes the path, prefixed with$unless it already starts with one.
-