executeStep function test exported
Last updated: 2026-03-05T20:45:07.036Z
Location
Metrics
LOC: 99
Complexity: 27
Params: 2
Signature
executeStep(
payload: ExecuteStepPayload,
): : Promise<StepResult>
Summary
Execute a single flow step in the current page. Returns a StepResult describing the outcome. Never throws.
Architecture violations
- [warning] max-cyclomatic-complexity: 'executeStep' has cyclomatic complexity 27 (max 10)
- [warning] max-lines: 'executeStep' has 99 lines (max 80)
Source Code
export async function executeStep(
payload: ExecuteStepPayload,
): Promise<StepResult> {
const { step, resolvedValue, replayConfig } = payload;
try {
let result: StepResult;
const selector =
step.smartSelectors?.[0]?.value ?? step.selector ?? undefined;
// Partition effects by timing (respecting per-kind defaults)
const allEffects: StepEffect[] = step.effects ?? [];
const byTiming = (t: "before" | "during" | "after") =>
allEffects.filter(
(e) => (e.timing ?? DEFAULT_EFFECT_TIMING[e.kind]) === t,
);
const beforeEffects = byTiming("before");
const duringEffects = byTiming("during");
const afterEffects = byTiming("after");
// 1. "before" effects complete fully before the action starts
if (beforeEffects.length) await applyStepEffects(beforeEffects, selector);
// 2. "during" effects start concurrently with the action
const duringPromise = duringEffects.length
? applyStepEffects(duringEffects, selector)
: Promise.resolve();
switch (step.action) {
case "navigate":
result = handleNavigate(step);
break;
case "fill":
result = await handleFill(step, resolvedValue, replayConfig);
break;
case "click":
result = handleClick(step);
break;
case "select":
result = handleSelect(step);
break;
case "check":
result = handleCheck(step, true);
break;
case "uncheck":
result = handleCheck(step, false);
break;
case "clear":
result = handleClear(step);
break;
case "wait":
result = await handleWait(step);
break;
case "scroll":
result = handleScroll(step);
break;
case "press-key":
result = handlePressKey(step);
break;
case "assert":
result = handleAssert(step);
break;
case "caption":
result = await handleCaption(step);
break;
default:
return { status: "skipped", reason: `Unknown action: ${step.action}` };
}
// Wait for "during" effects (they run in parallel with the action)
await duringPromise;
// Check if any "during" zoom effect was indefinite (duration 0 or Infinity)
// If so, cancel it now that the action is complete
const hasIndefiniteZoom = duringEffects.some(
(e) => e.kind === "zoom" && (e.duration === 0 || e.duration === Infinity),
);
if (hasIndefiniteZoom) {
cancelActiveZoom();
}
// 3. "after" effects run once the action has finished successfully
if (result.status === "success" && afterEffects.length) {
await applyStepEffects(afterEffects, selector);
}
return result;
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
log.warn(`Step ${step.id} failed:`, message);
if (step.optional) {
return { status: "skipped", reason: message };
}
return { status: "failed", error: message };
}
}
Dependencies (Outgoing)
| Target | Type |
|---|---|
| createLogger | uses |
| FlowStep | uses |
| StepResult | uses |
| ReplayConfig | uses |
| ExecuteStepPayload | uses |
| applyStepEffects | uses |
| showCaption | uses |
| cancelActiveZoom | uses |
| StepEffect | uses |
| handleNavigate | calls |
| handleFill | calls |
| handleClick | calls |
| handleSelect | calls |
| handleCheck | calls |
| handleClear | calls |
| handleWait | calls |
| handleScroll | calls |
| handlePressKey | calls |
| handleAssert | calls |
| handleCaption | calls |
Impact (Incoming)
| Source | Type |
|---|---|
| FillableElement | uses |
| assertFailed | uses |