stopRecording function exported ✓ 100.0%

Last updated: 2026-03-05T11:49:57.418Z

Metrics

LOC: 61 Complexity: 9 Params: 0 Coverage: 100.0% (14/14 lines, 0x executed)

Signature

stopRecording(): : RecordingSession | null

Summary

Stops recording and returns the complete session. Cleans up all event listeners and mutation observer.

Source Code

export function stopRecording(): RecordingSession | null {
  if (!session) return null;

  // If the network-idle timer is pending or requests were recently active,
  // flush a wait-for-network-idle step now (before the session status changes)
  // so the generated test correctly waits for in-flight requests.
  const recentNetworkActivity =
    lastNetworkActivityTimestamp > 0 &&
    now() - lastNetworkActivityTimestamp < 5_000;
  if (
    networkIdleTimer !== null ||
    pendingNetworkRequests > 0 ||
    recentNetworkActivity
  ) {
    if (networkIdleTimer) {
      clearTimeout(networkIdleTimer);
      networkIdleTimer = null;
    }
    const timeSinceLastAction = now() - lastActionTimestamp;
    if (timeSinceLastAction < 10_000) {
      // Push directly (addStep checks session.status === "recording" which is still true here)
      addStep({
        type: "wait-for-network-idle",
        timestamp: now(),
        label: "Wait for network requests to complete",
        waitTimeout: 10_000,
      });
    }
  }

  // Detach all event listeners
  for (const { target, event, handler } of listeners) {
    target.removeEventListener(event, handler, true);
    target.removeEventListener(event, handler);
  }
  listeners = [];

  // Stop mutation observer
  stopMutationObserver();

  // Stop network monitoring
  stopNetworkMonitoring();

  // Keep a reference (not a copy) to capturedResponses so that XHR loadend events
  // that fire after stop (in-flight at stop time) still populate stoppedResponses.
  // capturedResponses is reset to a fresh array in startRecording().
  stoppedResponses = capturedResponses;

  session.status = "stopped";
  lastActionTimestamp = 0;

  const final = session;
  stoppedSession = final; // preserve for export after recording ends
  session = null;

  // The user intentionally stopped recording — clear any persisted session so it
  // is not accidentally restored on the next page load.
  clearPersistedSession();

  return final;
}

Dependencies (Outgoing)

graph LR stopRecording["stopRecording"] now["now"] addStep["addStep"] stopMutationObserver["stopMutationObserver"] stopNetworkMonitoring["stopNetworkMonitoring"] clearPersistedSession["clearPersistedSession"] stopRecording -->|calls| now stopRecording -->|calls| addStep stopRecording -->|calls| stopMutationObserver stopRecording -->|calls| stopNetworkMonitoring stopRecording -->|calls| clearPersistedSession style stopRecording fill:#dbeafe,stroke:#2563eb,stroke-width:2px click stopRecording "26762b7cb59107d8.html" click now "b0f01bcc017e0081.html" click addStep "012da91201f9487b.html" click stopMutationObserver "92b26e547da48f34.html" click stopNetworkMonitoring "7f6f09a7586cc683.html" click clearPersistedSession "1bbf0d53387e33bf.html"

Impact (Incoming)

graph LR stopRecording["stopRecording"] FillableElement["FillableElement"] renderRecordTab["renderRecordTab"] startRecording["startRecording"] tryRestoreRecordingSession["tryRestoreRecordingSession"] FillableElement -->|uses| stopRecording renderRecordTab -->|calls| stopRecording startRecording -->|calls| stopRecording tryRestoreRecordingSession -->|calls| stopRecording style stopRecording fill:#dbeafe,stroke:#2563eb,stroke-width:2px click stopRecording "26762b7cb59107d8.html" click FillableElement "2ecf5aaac3f668a8.html" click renderRecordTab "55c03c4dd1c7d324.html" click startRecording "5a5a69de77cdf6a4.html" click tryRestoreRecordingSession "38d7b2802373484d.html"