-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Feature Description
Introduce a time-travel snapshot system in TWD that allows developers to capture and replay the DOM state at specific points during a test run. The system would work in SPA React applications and allow snapshots to be displayed in the TWD sidebar with element highlights, preserving visual fidelity without bloating memory.
Snapshots would primarily be triggered on:
- userEvent interactions (click, type, select, etc.)
- Assertions (
twd.should,el.should) - Optional explicit snapshot commands (
twd.snapshot())
Snapshots would exclude TWD UI/sidebar elements and avoid storing full CSS when possible by dynamically injecting current page styles during rendering.
Why is this feature needed?
Current TWD testing flows are linear and lack visual time-travel, which makes debugging failed interactions or flakey tests harder. Developers often need to:
- Understand the state of the DOM at specific interactions
- Visualize what a test “saw” at the time of an assertion
- Reproduce bugs in complex SPA flows
Without snapshots:
- Developers must manually inspect the DOM or rely on console logs
- Time-travel debugging is practically impossible
- Tests become harder to maintain and reason about
This feature would solve these pain points by giving developers a lightweight, memory-safe, visual record of test execution.
Proposed Solution
Key Principles
- Memory-efficient: store only HTML of the app root, up to a configurable limit (e.g., 15 snapshots)
- Exclude TWD UI: automatically remove sidebar or overlay elements during snapshot
- CSS fidelity: either keep external CSS or dynamically inject current page styles when rendering snapshot
- Highlight elements: allow optional overlay highlighting for interacted or asserted elements
- Trigger points: snapshots are captured after user interactions or assertions
API/Interface Design
Example usage in TWD tests:
import { describe, it } from "twd-js/runner";
import { twd, screenDom, userEvent } from "twd-js";
describe("Todo App", () => {
it("should add snapshot", async () => {
// User interactions trigger snapshots automatically
const addButton = screenDom.getByText("Add Task");
await userEvent.click(addButton);
// Optional manual snapshot
twd.snapshot("After adding task");
// Assertions can also trigger snapshots
twd.should(addButton, "be.visible");
// Later, in TWD sidebar:
// Display snapshot iframe with injected page styles and highlighted elements
});
});twd.snapshot(label?: string)→ captures a snapshot of the app root and stores metadata for the sidebar- Snapshots are stored in a rolling array, max length configurable (default 15)
- CSS is not stored inside the snapshot; current page
<style>and<link>tags are dynamically injected when rendering in the sidebar
Implementation Approach
- Snapshot Capture:
function takeSnapshot(label?: string) {
const container = document.querySelector("#app-root");
if (!container) return null;
const clone = container.cloneNode(true);
// Remove sidebar
clone.querySelector("#twd-sidebar-root")?.remove();
// Remove scripts
clone.querySelectorAll("script").forEach(s => s.remove());
const snapshotHTML = clone.outerHTML;
snapshots.push({ html: snapshotHTML, label, timestamp: Date.now() });
if (snapshots.length > MAX_SNAPSHOTS) snapshots.shift();
}- Snapshot Rendering:
// this in onHover
function renderSnapshot(iframe: HTMLIFrameElement, snapshot: string) {
const doc = iframe.contentDocument!;
// Inject current page CSS
const styles = Array.from(document.querySelectorAll("link[rel=stylesheet], style"));
doc.open();
styles.forEach(el => doc.head.appendChild(el.cloneNode(true)));
doc.write(snapshot);
doc.close();
}- Integration:
- Intercept
userEventandtwd.shouldto automatically trigger snapshots - Provide optional manual API for custom snapshots
- Display snapshots in sidebar with highlight overlays
Breaking Changes
None. Feature is additive and opt-in.
Testing Strategy
Test scenarios:
- Capture snapshot after a click → verify snapshot DOM matches app root
- Capture snapshot after a twd.should assertion → verify DOM is correctly saved
- Manual snapshot triggers → verify label and timestamp metadata
- Memory stress → create >15 snapshots → verify rolling array deletes oldest
- Snapshot rendering → verify iframe correctly renders DOM with styles
- Sidebar exclusion → verify #twd-sidebar-root is not included
- SPA navigation → capture snapshot in /dev, render in /todos → verify styles still apply
Benefits
- Time-travel debugging: inspect DOM at any interaction or assertion
- Memory-efficient: keeps snapshot footprint small
- Better developer experience: visual feedback in sidebar
- SPA-ready: works across routes without storing CSS in snapshots
- Minimal API overhead: opt-in manual snapshotting