@_deep4wee/agent-lens 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -30,6 +30,14 @@ declare const VIEWPORT_PRESETS: {
30
30
  /** Full HD */
31
31
  FULL_HD: ViewportPreset;
32
32
  };
33
+ interface MockRouteEntry {
34
+ url: string;
35
+ method?: string;
36
+ status?: number;
37
+ body: any;
38
+ delayMs?: number;
39
+ headers?: Record<string, string>;
40
+ }
33
41
  interface CaptureOptions {
34
42
  selector?: string;
35
43
  fullPage?: boolean;
@@ -105,17 +113,27 @@ interface TestContext {
105
113
  log: (message: string) => void;
106
114
  /**
107
115
  * Set a mock response for an IPC action.
108
- * Changes the data returned by window.external.sendMessage in preview mode.
116
+ * Changes the data returned by window.__mockIpc.invoke or hybrid bridges in preview mode.
109
117
  * Ignored in desktop mode (IPC goes through real backend).
110
- *
111
- * Example:
112
- * await ctx.setMockIpc('GET_INSTANCES', [{ id: '...', name: 'Test' }]);
113
- * await ctx.setMockIpc('CREATE_INSTANCE', 'Some error', { type: 'ERROR' });
114
118
  */
115
119
  setMockIpc: (action: string, data: any, options?: {
116
120
  type?: MockIpcResponseType;
117
121
  delayMs?: number;
118
122
  }) => Promise<void>;
123
+ /**
124
+ * Mock an HTTP REST or GraphQL network request in preview mode.
125
+ * Intercepts fetch/axios calls matching the URL pattern and returns mock data.
126
+ *
127
+ * Example:
128
+ * await ctx.setMockRoute('/api/user', { id: 1, name: 'Agent' });
129
+ * await ctx.setMockRoute('**\/api/items*', [], { status: 200, delayMs: 50 });
130
+ */
131
+ setMockRoute: (url: string, body: any, options?: {
132
+ method?: string;
133
+ status?: number;
134
+ delayMs?: number;
135
+ headers?: Record<string, string>;
136
+ }) => Promise<void>;
119
137
  /** Return all intercepted console.error and pageerror logs */
120
138
  getConsoleErrors: () => ConsoleEntry[];
121
139
  /** Return all intercepted console.warn logs */
@@ -143,15 +161,20 @@ interface VisualScenario {
143
161
  /** List of viewport sizes to test */
144
162
  viewports?: ViewportPreset[];
145
163
  /**
146
- * Initial IPC mock data for preview mode.
147
- * Applied BEFORE navigation to the route.
148
- */
164
+ * Initial IPC mock data for preview mode.
165
+ * Applied BEFORE navigation to the route.
166
+ */
149
167
  mockIpc?: Array<{
150
168
  action: string;
151
169
  data: any;
152
170
  type?: MockIpcResponseType;
153
171
  delayMs?: number;
154
172
  }>;
173
+ /**
174
+ * Initial HTTP REST/GraphQL route mocks for preview mode.
175
+ * Applied BEFORE navigation to the route.
176
+ */
177
+ mockRoutes?: MockRouteEntry[];
155
178
  /**
156
179
  * Optional setup hook: executed before the browser navigates and scenario runs.
157
180
  * Ideal for preparing mock files, test directories, or initial state.
@@ -167,4 +190,4 @@ interface VisualScenario {
167
190
  }
168
191
  declare function defineVisualTest(scenario: VisualScenario): VisualScenario;
169
192
 
170
- export { type CaptureBurstOptions, type CaptureOptions, type SnapshotMetadata, type TestContext, VIEWPORT_PRESETS, type ViewportPreset, type VisualScenario, defineVisualTest };
193
+ export { type CaptureBurstOptions, type CaptureOptions, type MockRouteEntry, type SnapshotMetadata, type TestContext, VIEWPORT_PRESETS, type ViewportPreset, type VisualScenario, defineVisualTest };
package/dist/index.d.ts CHANGED
@@ -30,6 +30,14 @@ declare const VIEWPORT_PRESETS: {
30
30
  /** Full HD */
31
31
  FULL_HD: ViewportPreset;
32
32
  };
33
+ interface MockRouteEntry {
34
+ url: string;
35
+ method?: string;
36
+ status?: number;
37
+ body: any;
38
+ delayMs?: number;
39
+ headers?: Record<string, string>;
40
+ }
33
41
  interface CaptureOptions {
34
42
  selector?: string;
35
43
  fullPage?: boolean;
@@ -105,17 +113,27 @@ interface TestContext {
105
113
  log: (message: string) => void;
106
114
  /**
107
115
  * Set a mock response for an IPC action.
108
- * Changes the data returned by window.external.sendMessage in preview mode.
116
+ * Changes the data returned by window.__mockIpc.invoke or hybrid bridges in preview mode.
109
117
  * Ignored in desktop mode (IPC goes through real backend).
110
- *
111
- * Example:
112
- * await ctx.setMockIpc('GET_INSTANCES', [{ id: '...', name: 'Test' }]);
113
- * await ctx.setMockIpc('CREATE_INSTANCE', 'Some error', { type: 'ERROR' });
114
118
  */
115
119
  setMockIpc: (action: string, data: any, options?: {
116
120
  type?: MockIpcResponseType;
117
121
  delayMs?: number;
118
122
  }) => Promise<void>;
123
+ /**
124
+ * Mock an HTTP REST or GraphQL network request in preview mode.
125
+ * Intercepts fetch/axios calls matching the URL pattern and returns mock data.
126
+ *
127
+ * Example:
128
+ * await ctx.setMockRoute('/api/user', { id: 1, name: 'Agent' });
129
+ * await ctx.setMockRoute('**\/api/items*', [], { status: 200, delayMs: 50 });
130
+ */
131
+ setMockRoute: (url: string, body: any, options?: {
132
+ method?: string;
133
+ status?: number;
134
+ delayMs?: number;
135
+ headers?: Record<string, string>;
136
+ }) => Promise<void>;
119
137
  /** Return all intercepted console.error and pageerror logs */
120
138
  getConsoleErrors: () => ConsoleEntry[];
121
139
  /** Return all intercepted console.warn logs */
@@ -143,15 +161,20 @@ interface VisualScenario {
143
161
  /** List of viewport sizes to test */
144
162
  viewports?: ViewportPreset[];
145
163
  /**
146
- * Initial IPC mock data for preview mode.
147
- * Applied BEFORE navigation to the route.
148
- */
164
+ * Initial IPC mock data for preview mode.
165
+ * Applied BEFORE navigation to the route.
166
+ */
149
167
  mockIpc?: Array<{
150
168
  action: string;
151
169
  data: any;
152
170
  type?: MockIpcResponseType;
153
171
  delayMs?: number;
154
172
  }>;
173
+ /**
174
+ * Initial HTTP REST/GraphQL route mocks for preview mode.
175
+ * Applied BEFORE navigation to the route.
176
+ */
177
+ mockRoutes?: MockRouteEntry[];
155
178
  /**
156
179
  * Optional setup hook: executed before the browser navigates and scenario runs.
157
180
  * Ideal for preparing mock files, test directories, or initial state.
@@ -167,4 +190,4 @@ interface VisualScenario {
167
190
  }
168
191
  declare function defineVisualTest(scenario: VisualScenario): VisualScenario;
169
192
 
170
- export { type CaptureBurstOptions, type CaptureOptions, type SnapshotMetadata, type TestContext, VIEWPORT_PRESETS, type ViewportPreset, type VisualScenario, defineVisualTest };
193
+ export { type CaptureBurstOptions, type CaptureOptions, type MockRouteEntry, type SnapshotMetadata, type TestContext, VIEWPORT_PRESETS, type ViewportPreset, type VisualScenario, defineVisualTest };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/api/dsl.ts"],"sourcesContent":["import type { Page, BrowserContext } from 'playwright';\nimport type { ConsoleEntry } from '../../features/console-tracker/consoleTracker';\nimport type { MockIpcResponseType } from '../../features/mock-ipc/mockIpc';\n\nexport interface ViewportPreset {\n name: string;\n width: number;\n height: number;\n}\n\nexport const VIEWPORT_PRESETS = {\n /** Minimum supported window size (e.g., ) */\n MIN_SUPPORTED: { name: 'min-supported', width: 1024, height: 768 } as ViewportPreset,\n /** Standard default window size (e.g., ) */\n DEFAULT: { name: 'default', width: 1200, height: 800 } as ViewportPreset,\n /** Wide screen for checking grids and tables */\n WIDE: { name: 'wide', width: 1600, height: 900 } as ViewportPreset,\n /** Full HD */\n FULL_HD: { name: 'full-hd', width: 1920, height: 1080 } as ViewportPreset,\n};\n\nexport interface CaptureOptions {\n selector?: string;\n fullPage?: boolean;\n mask?: string[];\n}\n\nexport interface CaptureBurstOptions {\n /** Total duration of burst animation capture in milliseconds */\n durationMs: number;\n /** Interval between frames in milliseconds (default: 80ms) */\n intervalMs?: number;\n /** Restrict capture to a specific element */\n selector?: string;\n}\n\nexport interface SnapshotMetadata {\n index: number;\n name: string;\n fileName: string;\n filePath: string;\n relativeUri: string;\n viewport: { width: number; height: number };\n timestamp: string;\n isBurstFrame?: boolean;\n burstGroup?: string;\n frameIndex?: number;\n selector?: string;\n}\n\nexport interface TestContext {\n page: Page;\n context: BrowserContext;\n targetMode: 'desktop' | 'preview';\n currentViewport: { width: number; height: number };\n \n // --- Snapshots ---\n\n /** Capture a single high-quality snapshot of the window or element */\n capture: (name: string, options?: CaptureOptions) => Promise<SnapshotMetadata>;\n \n /** Capture a series of frames for animations (Framer Motion, modals, lists) */\n captureBurst: (name: string, options: CaptureBurstOptions) => Promise<SnapshotMetadata[]>;\n \n // --- Navigation ---\n\n /** \n * Dynamically navigate to another page during the test.\n * Example: await ctx.navigate('/settings');\n */\n navigate: (route: string) => Promise<void>;\n\n // --- Viewport ---\n\n /** Change window / viewport size */\n resize: (width: number, height: number) => Promise<void>;\n \n /** Set one of the standard presets (MIN_SUPPORTED, DEFAULT, WIDE) */\n setPreset: (preset: ViewportPreset) => Promise<void>;\n\n /** \n * Dynamically resize the window so it perfectly fits the specified element (or body).\n * Useful when an agent wants to test an isolated component without background clutter.\n */\n resizeToFit: (selector?: string, padding?: number) => Promise<void>;\n \n // --- Waiting ---\n\n /** Wait the specified amount of milliseconds */\n wait: (ms: number) => Promise<void>;\n \n /** Wait for the selector to appear in the DOM */\n waitForSelector: (selector: string, timeoutMs?: number) => Promise<void>;\n \n // --- Interaction ---\n\n /** Left-click the element */\n click: (selector: string) => Promise<void>;\n \n /** Right-click the element (Context Menu) */\n rightClick: (selector: string) => Promise<void>;\n \n /** Type text into an input field */\n type: (selector: string, text: string) => Promise<void>;\n \n /** Select an option in a <select> by its value */\n selectOption: (selector: string, value: string) => Promise<void>;\n \n /** Hover the cursor to check highlights / tooltips */\n hover: (selector: string) => Promise<void>;\n \n /** Scroll the element (or window) down by the specified number of pixels */\n scroll: (selector: string, deltaY: number) => Promise<void>;\n \n // --- Logging ---\n\n /** Log a step for the agent */\n log: (message: string) => void;\n\n // --- Mock IPC (preview mode only) ---\n\n /**\n * Set a mock response for an IPC action.\n * Changes the data returned by window.external.sendMessage in preview mode.\n * Ignored in desktop mode (IPC goes through real backend).\n *\n * Example:\n * await ctx.setMockIpc('GET_INSTANCES', [{ id: '...', name: 'Test' }]);\n * await ctx.setMockIpc('CREATE_INSTANCE', 'Some error', { type: 'ERROR' });\n */\n setMockIpc: (action: string, data: any, options?: { type?: MockIpcResponseType; delayMs?: number }) => Promise<void>;\n\n // --- Console Errors ---\n\n /** Return all intercepted console.error and pageerror logs */\n getConsoleErrors: () => ConsoleEntry[];\n\n /** Return all intercepted console.warn logs */\n getConsoleWarnings: () => ConsoleEntry[];\n\n /** Returns true if there are critical errors in the console */\n hasConsoleErrors: () => boolean;\n\n // --- DOM Assertions ---\n\n /** Get the visible text of a specific element */\n readText: (selector: string) => Promise<string | null>;\n \n /** Get ALL visible text on the page (useful for quick analysis without Vision) */\n getPageText: () => Promise<string>;\n \n /** Check if the element is visible on the screen */\n isVisible: (selector: string) => Promise<boolean>;\n\n /** Count the number of elements matching the selector */\n getElementCount: (selector: string) => Promise<number>;\n}\n\nexport interface VisualScenario {\n /** Unique scenario identifier (kebab-case) */\n id: string;\n /** Human-readable title for the report */\n title: string;\n /** Description of what is being tested */\n description?: string;\n /** Initial route to navigate to (e.g., '/instances', '/settings') */\n route?: string;\n /** List of viewport sizes to test */\n viewports?: ViewportPreset[];\n /**\n * Initial IPC mock data for preview mode.\n * Applied BEFORE navigation to the route.\n */\n mockIpc?: Array<{ action: string; data: any; type?: MockIpcResponseType; delayMs?: number }>;\n /**\n * Optional setup hook: executed before the browser navigates and scenario runs.\n * Ideal for preparing mock files, test directories, or initial state.\n */\n setup?: () => Promise<void> | void;\n /** The main body of the scenario */\n run: (ctx: TestContext) => Promise<void>;\n /**\n * Optional teardown hook: guaranteed to execute in finally, even if run() fails.\n * Ideal for cleaning up test artifacts, cache directories, or temporary state.\n */\n teardown?: () => Promise<void> | void;\n}\n\nexport function defineVisualTest(scenario: VisualScenario): VisualScenario {\n return scenario;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUO,IAAM,mBAAmB;AAAA;AAAA,EAE9B,eAAe,EAAE,MAAM,iBAAiB,OAAO,MAAM,QAAQ,IAAI;AAAA;AAAA,EAEjE,SAAS,EAAE,MAAM,WAAW,OAAO,MAAM,QAAQ,IAAI;AAAA;AAAA,EAErD,MAAM,EAAE,MAAM,QAAQ,OAAO,MAAM,QAAQ,IAAI;AAAA;AAAA,EAE/C,SAAS,EAAE,MAAM,WAAW,OAAO,MAAM,QAAQ,KAAK;AACxD;AAyKO,SAAS,iBAAiB,UAA0C;AACzE,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/shared/api/dsl.ts"],"sourcesContent":["import type { Page, BrowserContext } from 'playwright';\nimport type { ConsoleEntry } from '../../features/console-tracker/consoleTracker';\nimport type { MockIpcResponseType } from '../../features/mock-ipc/mockIpc';\n\nexport interface ViewportPreset {\n name: string;\n width: number;\n height: number;\n}\n\nexport const VIEWPORT_PRESETS = {\n /** Minimum supported window size (e.g., ) */\n MIN_SUPPORTED: { name: 'min-supported', width: 1024, height: 768 } as ViewportPreset,\n /** Standard default window size (e.g., ) */\n DEFAULT: { name: 'default', width: 1200, height: 800 } as ViewportPreset,\n /** Wide screen for checking grids and tables */\n WIDE: { name: 'wide', width: 1600, height: 900 } as ViewportPreset,\n /** Full HD */\n FULL_HD: { name: 'full-hd', width: 1920, height: 1080 } as ViewportPreset,\n};\n\nexport interface MockRouteEntry {\n url: string;\n method?: string;\n status?: number;\n body: any;\n delayMs?: number;\n headers?: Record<string, string>;\n}\n\nexport interface CaptureOptions {\n selector?: string;\n fullPage?: boolean;\n mask?: string[];\n}\n \n\nexport interface CaptureBurstOptions {\n /** Total duration of burst animation capture in milliseconds */\n durationMs: number;\n /** Interval between frames in milliseconds (default: 80ms) */\n intervalMs?: number;\n /** Restrict capture to a specific element */\n selector?: string;\n}\n\nexport interface SnapshotMetadata {\n index: number;\n name: string;\n fileName: string;\n filePath: string;\n relativeUri: string;\n viewport: { width: number; height: number };\n timestamp: string;\n isBurstFrame?: boolean;\n burstGroup?: string;\n frameIndex?: number;\n selector?: string;\n}\n\nexport interface TestContext {\n page: Page;\n context: BrowserContext;\n targetMode: 'desktop' | 'preview';\n currentViewport: { width: number; height: number };\n \n // --- Snapshots ---\n\n /** Capture a single high-quality snapshot of the window or element */\n capture: (name: string, options?: CaptureOptions) => Promise<SnapshotMetadata>;\n \n /** Capture a series of frames for animations (Framer Motion, modals, lists) */\n captureBurst: (name: string, options: CaptureBurstOptions) => Promise<SnapshotMetadata[]>;\n \n // --- Navigation ---\n\n /** \n * Dynamically navigate to another page during the test.\n * Example: await ctx.navigate('/settings');\n */\n navigate: (route: string) => Promise<void>;\n\n // --- Viewport ---\n\n /** Change window / viewport size */\n resize: (width: number, height: number) => Promise<void>;\n \n /** Set one of the standard presets (MIN_SUPPORTED, DEFAULT, WIDE) */\n setPreset: (preset: ViewportPreset) => Promise<void>;\n\n /** \n * Dynamically resize the window so it perfectly fits the specified element (or body).\n * Useful when an agent wants to test an isolated component without background clutter.\n */\n resizeToFit: (selector?: string, padding?: number) => Promise<void>;\n \n // --- Waiting ---\n\n /** Wait the specified amount of milliseconds */\n wait: (ms: number) => Promise<void>;\n \n /** Wait for the selector to appear in the DOM */\n waitForSelector: (selector: string, timeoutMs?: number) => Promise<void>;\n \n // --- Interaction ---\n\n /** Left-click the element */\n click: (selector: string) => Promise<void>;\n \n /** Right-click the element (Context Menu) */\n rightClick: (selector: string) => Promise<void>;\n \n /** Type text into an input field */\n type: (selector: string, text: string) => Promise<void>;\n \n /** Select an option in a <select> by its value */\n selectOption: (selector: string, value: string) => Promise<void>;\n \n /** Hover the cursor to check highlights / tooltips */\n hover: (selector: string) => Promise<void>;\n \n /** Scroll the element (or window) down by the specified number of pixels */\n scroll: (selector: string, deltaY: number) => Promise<void>;\n \n // --- Logging ---\n\n /** Log a step for the agent */\n log: (message: string) => void;\n\n // --- Mock IPC & Network Routes (preview mode only) ---\n\n /**\n * Set a mock response for an IPC action.\n * Changes the data returned by window.__mockIpc.invoke or hybrid bridges in preview mode.\n * Ignored in desktop mode (IPC goes through real backend).\n */\n setMockIpc: (action: string, data: any, options?: { type?: MockIpcResponseType; delayMs?: number }) => Promise<void>;\n\n /**\n * Mock an HTTP REST or GraphQL network request in preview mode.\n * Intercepts fetch/axios calls matching the URL pattern and returns mock data.\n *\n * Example:\n * await ctx.setMockRoute('/api/user', { id: 1, name: 'Agent' });\n * await ctx.setMockRoute('**\\/api/items*', [], { status: 200, delayMs: 50 });\n */\n setMockRoute: (\n url: string,\n body: any,\n options?: { method?: string; status?: number; delayMs?: number; headers?: Record<string, string> }\n ) => Promise<void>;\n\n // --- Console Errors ---\n \n\n /** Return all intercepted console.error and pageerror logs */\n getConsoleErrors: () => ConsoleEntry[];\n\n /** Return all intercepted console.warn logs */\n getConsoleWarnings: () => ConsoleEntry[];\n\n /** Returns true if there are critical errors in the console */\n hasConsoleErrors: () => boolean;\n\n // --- DOM Assertions ---\n\n /** Get the visible text of a specific element */\n readText: (selector: string) => Promise<string | null>;\n \n /** Get ALL visible text on the page (useful for quick analysis without Vision) */\n getPageText: () => Promise<string>;\n \n /** Check if the element is visible on the screen */\n isVisible: (selector: string) => Promise<boolean>;\n\n /** Count the number of elements matching the selector */\n getElementCount: (selector: string) => Promise<number>;\n}\n\nexport interface VisualScenario {\n /** Unique scenario identifier (kebab-case) */\n id: string;\n /** Human-readable title for the report */\n title: string;\n /** Description of what is being tested */\n description?: string;\n /** Initial route to navigate to (e.g., '/instances', '/settings') */\n route?: string;\n /** List of viewport sizes to test */\n viewports?: ViewportPreset[];\n /**\n * Initial IPC mock data for preview mode.\n * Applied BEFORE navigation to the route.\n */\n mockIpc?: Array<{ action: string; data: any; type?: MockIpcResponseType; delayMs?: number }>;\n /**\n * Initial HTTP REST/GraphQL route mocks for preview mode.\n * Applied BEFORE navigation to the route.\n */\n mockRoutes?: MockRouteEntry[];\n /**\n * Optional setup hook: executed before the browser navigates and scenario runs.\n * Ideal for preparing mock files, test directories, or initial state.\n */\n \n setup?: () => Promise<void> | void;\n /** The main body of the scenario */\n run: (ctx: TestContext) => Promise<void>;\n /**\n * Optional teardown hook: guaranteed to execute in finally, even if run() fails.\n * Ideal for cleaning up test artifacts, cache directories, or temporary state.\n */\n teardown?: () => Promise<void> | void;\n}\n\nexport function defineVisualTest(scenario: VisualScenario): VisualScenario {\n return scenario;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUO,IAAM,mBAAmB;AAAA;AAAA,EAE9B,eAAe,EAAE,MAAM,iBAAiB,OAAO,MAAM,QAAQ,IAAI;AAAA;AAAA,EAEjE,SAAS,EAAE,MAAM,WAAW,OAAO,MAAM,QAAQ,IAAI;AAAA;AAAA,EAErD,MAAM,EAAE,MAAM,QAAQ,OAAO,MAAM,QAAQ,IAAI;AAAA;AAAA,EAE/C,SAAS,EAAE,MAAM,WAAW,OAAO,MAAM,QAAQ,KAAK;AACxD;AAoMO,SAAS,iBAAiB,UAA0C;AACzE,SAAO;AACT;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/api/dsl.ts"],"sourcesContent":["import type { Page, BrowserContext } from 'playwright';\nimport type { ConsoleEntry } from '../../features/console-tracker/consoleTracker';\nimport type { MockIpcResponseType } from '../../features/mock-ipc/mockIpc';\n\nexport interface ViewportPreset {\n name: string;\n width: number;\n height: number;\n}\n\nexport const VIEWPORT_PRESETS = {\n /** Minimum supported window size (e.g., ) */\n MIN_SUPPORTED: { name: 'min-supported', width: 1024, height: 768 } as ViewportPreset,\n /** Standard default window size (e.g., ) */\n DEFAULT: { name: 'default', width: 1200, height: 800 } as ViewportPreset,\n /** Wide screen for checking grids and tables */\n WIDE: { name: 'wide', width: 1600, height: 900 } as ViewportPreset,\n /** Full HD */\n FULL_HD: { name: 'full-hd', width: 1920, height: 1080 } as ViewportPreset,\n};\n\nexport interface CaptureOptions {\n selector?: string;\n fullPage?: boolean;\n mask?: string[];\n}\n\nexport interface CaptureBurstOptions {\n /** Total duration of burst animation capture in milliseconds */\n durationMs: number;\n /** Interval between frames in milliseconds (default: 80ms) */\n intervalMs?: number;\n /** Restrict capture to a specific element */\n selector?: string;\n}\n\nexport interface SnapshotMetadata {\n index: number;\n name: string;\n fileName: string;\n filePath: string;\n relativeUri: string;\n viewport: { width: number; height: number };\n timestamp: string;\n isBurstFrame?: boolean;\n burstGroup?: string;\n frameIndex?: number;\n selector?: string;\n}\n\nexport interface TestContext {\n page: Page;\n context: BrowserContext;\n targetMode: 'desktop' | 'preview';\n currentViewport: { width: number; height: number };\n \n // --- Snapshots ---\n\n /** Capture a single high-quality snapshot of the window or element */\n capture: (name: string, options?: CaptureOptions) => Promise<SnapshotMetadata>;\n \n /** Capture a series of frames for animations (Framer Motion, modals, lists) */\n captureBurst: (name: string, options: CaptureBurstOptions) => Promise<SnapshotMetadata[]>;\n \n // --- Navigation ---\n\n /** \n * Dynamically navigate to another page during the test.\n * Example: await ctx.navigate('/settings');\n */\n navigate: (route: string) => Promise<void>;\n\n // --- Viewport ---\n\n /** Change window / viewport size */\n resize: (width: number, height: number) => Promise<void>;\n \n /** Set one of the standard presets (MIN_SUPPORTED, DEFAULT, WIDE) */\n setPreset: (preset: ViewportPreset) => Promise<void>;\n\n /** \n * Dynamically resize the window so it perfectly fits the specified element (or body).\n * Useful when an agent wants to test an isolated component without background clutter.\n */\n resizeToFit: (selector?: string, padding?: number) => Promise<void>;\n \n // --- Waiting ---\n\n /** Wait the specified amount of milliseconds */\n wait: (ms: number) => Promise<void>;\n \n /** Wait for the selector to appear in the DOM */\n waitForSelector: (selector: string, timeoutMs?: number) => Promise<void>;\n \n // --- Interaction ---\n\n /** Left-click the element */\n click: (selector: string) => Promise<void>;\n \n /** Right-click the element (Context Menu) */\n rightClick: (selector: string) => Promise<void>;\n \n /** Type text into an input field */\n type: (selector: string, text: string) => Promise<void>;\n \n /** Select an option in a <select> by its value */\n selectOption: (selector: string, value: string) => Promise<void>;\n \n /** Hover the cursor to check highlights / tooltips */\n hover: (selector: string) => Promise<void>;\n \n /** Scroll the element (or window) down by the specified number of pixels */\n scroll: (selector: string, deltaY: number) => Promise<void>;\n \n // --- Logging ---\n\n /** Log a step for the agent */\n log: (message: string) => void;\n\n // --- Mock IPC (preview mode only) ---\n\n /**\n * Set a mock response for an IPC action.\n * Changes the data returned by window.external.sendMessage in preview mode.\n * Ignored in desktop mode (IPC goes through real backend).\n *\n * Example:\n * await ctx.setMockIpc('GET_INSTANCES', [{ id: '...', name: 'Test' }]);\n * await ctx.setMockIpc('CREATE_INSTANCE', 'Some error', { type: 'ERROR' });\n */\n setMockIpc: (action: string, data: any, options?: { type?: MockIpcResponseType; delayMs?: number }) => Promise<void>;\n\n // --- Console Errors ---\n\n /** Return all intercepted console.error and pageerror logs */\n getConsoleErrors: () => ConsoleEntry[];\n\n /** Return all intercepted console.warn logs */\n getConsoleWarnings: () => ConsoleEntry[];\n\n /** Returns true if there are critical errors in the console */\n hasConsoleErrors: () => boolean;\n\n // --- DOM Assertions ---\n\n /** Get the visible text of a specific element */\n readText: (selector: string) => Promise<string | null>;\n \n /** Get ALL visible text on the page (useful for quick analysis without Vision) */\n getPageText: () => Promise<string>;\n \n /** Check if the element is visible on the screen */\n isVisible: (selector: string) => Promise<boolean>;\n\n /** Count the number of elements matching the selector */\n getElementCount: (selector: string) => Promise<number>;\n}\n\nexport interface VisualScenario {\n /** Unique scenario identifier (kebab-case) */\n id: string;\n /** Human-readable title for the report */\n title: string;\n /** Description of what is being tested */\n description?: string;\n /** Initial route to navigate to (e.g., '/instances', '/settings') */\n route?: string;\n /** List of viewport sizes to test */\n viewports?: ViewportPreset[];\n /**\n * Initial IPC mock data for preview mode.\n * Applied BEFORE navigation to the route.\n */\n mockIpc?: Array<{ action: string; data: any; type?: MockIpcResponseType; delayMs?: number }>;\n /**\n * Optional setup hook: executed before the browser navigates and scenario runs.\n * Ideal for preparing mock files, test directories, or initial state.\n */\n setup?: () => Promise<void> | void;\n /** The main body of the scenario */\n run: (ctx: TestContext) => Promise<void>;\n /**\n * Optional teardown hook: guaranteed to execute in finally, even if run() fails.\n * Ideal for cleaning up test artifacts, cache directories, or temporary state.\n */\n teardown?: () => Promise<void> | void;\n}\n\nexport function defineVisualTest(scenario: VisualScenario): VisualScenario {\n return scenario;\n}\n"],"mappings":";AAUO,IAAM,mBAAmB;AAAA;AAAA,EAE9B,eAAe,EAAE,MAAM,iBAAiB,OAAO,MAAM,QAAQ,IAAI;AAAA;AAAA,EAEjE,SAAS,EAAE,MAAM,WAAW,OAAO,MAAM,QAAQ,IAAI;AAAA;AAAA,EAErD,MAAM,EAAE,MAAM,QAAQ,OAAO,MAAM,QAAQ,IAAI;AAAA;AAAA,EAE/C,SAAS,EAAE,MAAM,WAAW,OAAO,MAAM,QAAQ,KAAK;AACxD;AAyKO,SAAS,iBAAiB,UAA0C;AACzE,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/shared/api/dsl.ts"],"sourcesContent":["import type { Page, BrowserContext } from 'playwright';\nimport type { ConsoleEntry } from '../../features/console-tracker/consoleTracker';\nimport type { MockIpcResponseType } from '../../features/mock-ipc/mockIpc';\n\nexport interface ViewportPreset {\n name: string;\n width: number;\n height: number;\n}\n\nexport const VIEWPORT_PRESETS = {\n /** Minimum supported window size (e.g., ) */\n MIN_SUPPORTED: { name: 'min-supported', width: 1024, height: 768 } as ViewportPreset,\n /** Standard default window size (e.g., ) */\n DEFAULT: { name: 'default', width: 1200, height: 800 } as ViewportPreset,\n /** Wide screen for checking grids and tables */\n WIDE: { name: 'wide', width: 1600, height: 900 } as ViewportPreset,\n /** Full HD */\n FULL_HD: { name: 'full-hd', width: 1920, height: 1080 } as ViewportPreset,\n};\n\nexport interface MockRouteEntry {\n url: string;\n method?: string;\n status?: number;\n body: any;\n delayMs?: number;\n headers?: Record<string, string>;\n}\n\nexport interface CaptureOptions {\n selector?: string;\n fullPage?: boolean;\n mask?: string[];\n}\n \n\nexport interface CaptureBurstOptions {\n /** Total duration of burst animation capture in milliseconds */\n durationMs: number;\n /** Interval between frames in milliseconds (default: 80ms) */\n intervalMs?: number;\n /** Restrict capture to a specific element */\n selector?: string;\n}\n\nexport interface SnapshotMetadata {\n index: number;\n name: string;\n fileName: string;\n filePath: string;\n relativeUri: string;\n viewport: { width: number; height: number };\n timestamp: string;\n isBurstFrame?: boolean;\n burstGroup?: string;\n frameIndex?: number;\n selector?: string;\n}\n\nexport interface TestContext {\n page: Page;\n context: BrowserContext;\n targetMode: 'desktop' | 'preview';\n currentViewport: { width: number; height: number };\n \n // --- Snapshots ---\n\n /** Capture a single high-quality snapshot of the window or element */\n capture: (name: string, options?: CaptureOptions) => Promise<SnapshotMetadata>;\n \n /** Capture a series of frames for animations (Framer Motion, modals, lists) */\n captureBurst: (name: string, options: CaptureBurstOptions) => Promise<SnapshotMetadata[]>;\n \n // --- Navigation ---\n\n /** \n * Dynamically navigate to another page during the test.\n * Example: await ctx.navigate('/settings');\n */\n navigate: (route: string) => Promise<void>;\n\n // --- Viewport ---\n\n /** Change window / viewport size */\n resize: (width: number, height: number) => Promise<void>;\n \n /** Set one of the standard presets (MIN_SUPPORTED, DEFAULT, WIDE) */\n setPreset: (preset: ViewportPreset) => Promise<void>;\n\n /** \n * Dynamically resize the window so it perfectly fits the specified element (or body).\n * Useful when an agent wants to test an isolated component without background clutter.\n */\n resizeToFit: (selector?: string, padding?: number) => Promise<void>;\n \n // --- Waiting ---\n\n /** Wait the specified amount of milliseconds */\n wait: (ms: number) => Promise<void>;\n \n /** Wait for the selector to appear in the DOM */\n waitForSelector: (selector: string, timeoutMs?: number) => Promise<void>;\n \n // --- Interaction ---\n\n /** Left-click the element */\n click: (selector: string) => Promise<void>;\n \n /** Right-click the element (Context Menu) */\n rightClick: (selector: string) => Promise<void>;\n \n /** Type text into an input field */\n type: (selector: string, text: string) => Promise<void>;\n \n /** Select an option in a <select> by its value */\n selectOption: (selector: string, value: string) => Promise<void>;\n \n /** Hover the cursor to check highlights / tooltips */\n hover: (selector: string) => Promise<void>;\n \n /** Scroll the element (or window) down by the specified number of pixels */\n scroll: (selector: string, deltaY: number) => Promise<void>;\n \n // --- Logging ---\n\n /** Log a step for the agent */\n log: (message: string) => void;\n\n // --- Mock IPC & Network Routes (preview mode only) ---\n\n /**\n * Set a mock response for an IPC action.\n * Changes the data returned by window.__mockIpc.invoke or hybrid bridges in preview mode.\n * Ignored in desktop mode (IPC goes through real backend).\n */\n setMockIpc: (action: string, data: any, options?: { type?: MockIpcResponseType; delayMs?: number }) => Promise<void>;\n\n /**\n * Mock an HTTP REST or GraphQL network request in preview mode.\n * Intercepts fetch/axios calls matching the URL pattern and returns mock data.\n *\n * Example:\n * await ctx.setMockRoute('/api/user', { id: 1, name: 'Agent' });\n * await ctx.setMockRoute('**\\/api/items*', [], { status: 200, delayMs: 50 });\n */\n setMockRoute: (\n url: string,\n body: any,\n options?: { method?: string; status?: number; delayMs?: number; headers?: Record<string, string> }\n ) => Promise<void>;\n\n // --- Console Errors ---\n \n\n /** Return all intercepted console.error and pageerror logs */\n getConsoleErrors: () => ConsoleEntry[];\n\n /** Return all intercepted console.warn logs */\n getConsoleWarnings: () => ConsoleEntry[];\n\n /** Returns true if there are critical errors in the console */\n hasConsoleErrors: () => boolean;\n\n // --- DOM Assertions ---\n\n /** Get the visible text of a specific element */\n readText: (selector: string) => Promise<string | null>;\n \n /** Get ALL visible text on the page (useful for quick analysis without Vision) */\n getPageText: () => Promise<string>;\n \n /** Check if the element is visible on the screen */\n isVisible: (selector: string) => Promise<boolean>;\n\n /** Count the number of elements matching the selector */\n getElementCount: (selector: string) => Promise<number>;\n}\n\nexport interface VisualScenario {\n /** Unique scenario identifier (kebab-case) */\n id: string;\n /** Human-readable title for the report */\n title: string;\n /** Description of what is being tested */\n description?: string;\n /** Initial route to navigate to (e.g., '/instances', '/settings') */\n route?: string;\n /** List of viewport sizes to test */\n viewports?: ViewportPreset[];\n /**\n * Initial IPC mock data for preview mode.\n * Applied BEFORE navigation to the route.\n */\n mockIpc?: Array<{ action: string; data: any; type?: MockIpcResponseType; delayMs?: number }>;\n /**\n * Initial HTTP REST/GraphQL route mocks for preview mode.\n * Applied BEFORE navigation to the route.\n */\n mockRoutes?: MockRouteEntry[];\n /**\n * Optional setup hook: executed before the browser navigates and scenario runs.\n * Ideal for preparing mock files, test directories, or initial state.\n */\n \n setup?: () => Promise<void> | void;\n /** The main body of the scenario */\n run: (ctx: TestContext) => Promise<void>;\n /**\n * Optional teardown hook: guaranteed to execute in finally, even if run() fails.\n * Ideal for cleaning up test artifacts, cache directories, or temporary state.\n */\n teardown?: () => Promise<void> | void;\n}\n\nexport function defineVisualTest(scenario: VisualScenario): VisualScenario {\n return scenario;\n}\n"],"mappings":";AAUO,IAAM,mBAAmB;AAAA;AAAA,EAE9B,eAAe,EAAE,MAAM,iBAAiB,OAAO,MAAM,QAAQ,IAAI;AAAA;AAAA,EAEjE,SAAS,EAAE,MAAM,WAAW,OAAO,MAAM,QAAQ,IAAI;AAAA;AAAA,EAErD,MAAM,EAAE,MAAM,QAAQ,OAAO,MAAM,QAAQ,IAAI;AAAA;AAAA,EAE/C,SAAS,EAAE,MAAM,WAAW,OAAO,MAAM,QAAQ,KAAK;AACxD;AAoMO,SAAS,iBAAiB,UAA0C;AACzE,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@_deep4wee/agent-lens",
3
- "version": "1.0.1",
4
- "description": "Visual self-check UI runner for AI coding agents",
3
+ "version": "1.1.0",
4
+ "description": "Visual self-check UI runner for AI coding agents",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "bin": {
@@ -27,7 +27,7 @@
27
27
  "playwright": "^1.40.0"
28
28
  },
29
29
  "devDependencies": {
30
- "@types/node": "^20.0.0",
30
+ "@types/node": "^20.19.43",
31
31
  "playwright": "^1.63.0",
32
32
  "tsup": "^8.0.2",
33
33
  "typescript": "^5.0.0"
@@ -48,11 +48,15 @@ npx agent-lens --scenario=checkout-flow --url=http://localhost:5173
48
48
  npx agent-lens snap --url=http://localhost:5173
49
49
  ```
50
50
  4. **Inspect the Output**:
51
- - AgentLens always writes the latest report to:
51
+ - AgentLens always synchronizes the most recent run to:
52
52
  `artifacts/latest/report.md`
53
- - Use `view_file` to read `artifacts/latest/report.md` immediately without worrying about timestamped folder names.
54
- - Check the **Console Errors** section — if errors exist, fix them!
55
- 5. **Self-Correct & Iterate**: Re-run verification until the layout is solid and the console is clean.
53
+ - **Step 1 (Check Logs & Console)**: Use your file reading tool (`view_file`, `cat`) on `artifacts/latest/report.md`. If there are any **Console Errors**, fix the JavaScript / React exceptions first.
54
+ - **Step 2 (Vision Visual Check)**: If your environment supports multimodal / vision tools (e.g. `view_image`), inspect the latest generated screenshots directly:
55
+ `artifacts/latest/01_quick_snap_desktop.png`
56
+ `artifacts/latest/02_quick_snap_mobile.png`
57
+ Look for text overflow, unwanted horizontal scrolling, broken CSS flex/grid layouts, or misaligned elements.
58
+ 5. **Self-Correct & Iterate**: Re-run verification until the layout is visually solid and the console is clean.
59
+
56
60
 
57
61
  ---
58
62
 
@@ -139,6 +143,17 @@ export default defineVisualTest({
139
143
  title: 'Feature Verification',
140
144
  route: '/dashboard', // Route or URL
141
145
  viewports: [VIEWPORT_PRESETS.DEFAULT, VIEWPORT_PRESETS.MIN_SUPPORTED],
146
+
147
+ // HTTP REST / GraphQL Network Mocks (Vite / Next.js / Web SPA)
148
+ mockRoutes: [
149
+ { url: '**/api/v1/user', body: { id: 1, name: 'Agent', role: 'admin' } },
150
+ { url: '**/api/v1/stats', body: { total: 42, active: 10 } }
151
+ ],
152
+
153
+ // Optional Hybrid / IPC mocks
154
+ mockIpc: [
155
+ { action: 'GET_PREFS', data: { theme: 'dark' } }
156
+ ],
142
157
 
143
158
  // Lifecycle Setup: prepare temporary state or mock folders
144
159
  setup: async () => {},
@@ -150,6 +165,7 @@ export default defineVisualTest({
150
165
  teardown: async () => {}
151
166
  });
152
167
  ```
168
+
153
169
 
154
170
  ### Available `ctx` Methods:
155
171
 
@@ -184,8 +200,10 @@ export default defineVisualTest({
184
200
  - `ctx.getConsoleErrors()`: Array of caught errors with stack traces.
185
201
  - `ctx.getConsoleWarnings()`: Array of caught warnings.
186
202
 
187
- #### 🎭 Dynamic Mock IPC (Web / Preview mode)
188
- - `await ctx.setMockIpc('ACTION_NAME', payload, { type: 'SUCCESS' | 'ERROR', delayMs?: number })`: Dynamically alters mock data during test execution.
203
+ #### 🌐 Network Route & Mock IPC (Preview mode)
204
+ - `await ctx.setMockRoute('**/api/users', payload, options?)`: Dynamically intercepts HTTP/REST API endpoints and returns mock JSON or status codes.
205
+ - `await ctx.setMockIpc('ACTION_NAME', payload, { type: 'SUCCESS' | 'ERROR', delayMs?: number })`: Dynamically alters mock data for hybrid IPC bridges.
206
+
189
207
 
190
208
  ---
191
209
 
@@ -1,11 +1,11 @@
1
- # Example 6: State Testing with Mock IPC
1
+ # Example 6: State Testing with Mock Routes & Mock IPC
2
2
 
3
3
  Simulate different application states (empty list, loading spinners, network errors, populated data) without running a real backend.
4
4
 
5
5
  ## Use Cases
6
- - Verifying Empty States ("No items found").
7
- - Testing Error Boundaries and error banners when an API fails.
8
- - Testing data table pagination and high volume data.
6
+ - Verifying HTTP REST / GraphQL states (Empty state, Populated state, 500 Internal Error).
7
+ - Testing React Error Boundaries and error banners when an API endpoint fails.
8
+ - Testing data table pagination and high volume data without database seeding.
9
9
 
10
10
  ## Writing the Scenario (`scenarios/states.scenario.ts`)
11
11
 
@@ -17,11 +17,11 @@ export default defineVisualTest({
17
17
  title: 'Empty State vs Populated State Verification',
18
18
  route: '/users',
19
19
 
20
- // 1. Initial State: Populated list
21
- mockIpc: [
20
+ // 1. Initial HTTP Network Mocks (Works with fetch/axios in React, Vue, Next.js)
21
+ mockRoutes: [
22
22
  {
23
- action: 'GET_USERS',
24
- data: [
23
+ url: '**/api/users',
24
+ body: [
25
25
  { id: 1, name: 'Alice Cooper', role: 'Administrator' },
26
26
  { id: 2, name: 'Bob Marley', role: 'Editor' }
27
27
  ]
@@ -35,7 +35,7 @@ export default defineVisualTest({
35
35
 
36
36
  // 2. Dynamically swap mock data to Empty State during the test
37
37
  ctx.log('2. Updating mock to empty list');
38
- await ctx.setMockIpc('GET_USERS', []);
38
+ await ctx.setMockRoute('**/api/users', []);
39
39
 
40
40
  // Re-navigate or trigger refresh
41
41
  await ctx.navigate('/users');
@@ -46,15 +46,16 @@ export default defineVisualTest({
46
46
  const hasEmptyMessage = await ctx.isVisible('text="No users found"');
47
47
  ctx.log(`Empty state text visible: ${hasEmptyMessage}`);
48
48
 
49
- // 3. Dynamically simulate API Error
50
- ctx.log('3. Simulating backend failure');
51
- await ctx.setMockIpc('GET_USERS', 'Internal Server Error (500)', { type: 'ERROR' });
49
+ // 3. Dynamically simulate HTTP 500 Backend Failure
50
+ ctx.log('3. Simulating backend 500 failure');
51
+ await ctx.setMockRoute('**/api/users', { error: 'Internal Server Error' }, { status: 500 });
52
52
  await ctx.navigate('/users');
53
53
  await ctx.wait(300);
54
54
  await ctx.capture('03_users_error_state');
55
55
  }
56
56
  });
57
57
  ```
58
+
58
59
 
59
60
  ## Running the Scenario
60
61
  ```bash