@_deep4wee/agent-lens 1.0.1
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/LICENSE +21 -0
- package/README.md +221 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1853 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +1924 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +170 -0
- package/dist/index.d.ts +170 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +19 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +60 -0
- package/scripts/postinstall.js +47 -0
- package/skills/agent-lens/SKILL.md +200 -0
- package/skills/agent-lens/examples/01-instant-verification-snap.md +53 -0
- package/skills/agent-lens/examples/02-dev-server-live-testing.md +62 -0
- package/skills/agent-lens/examples/03-component-isolation-and-animations.md +53 -0
- package/skills/agent-lens/examples/04-desktop-native-testing.md +68 -0
- package/skills/agent-lens/examples/05-clean-teardown-and-sandboxing.md +68 -0
- package/skills/agent-lens/examples/06-state-testing-with-mock-ipc.md +62 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Example 2: Live Dev Server Workflow
|
|
2
|
+
|
|
3
|
+
Test complex user flows and route transitions on an active Vite, Next.js, Webpack, or Full-Stack dev server.
|
|
4
|
+
|
|
5
|
+
## Use Cases
|
|
6
|
+
- Testing forms, multi-step wizards, and client-side navigation.
|
|
7
|
+
- Verifying client-server interactions against real endpoints.
|
|
8
|
+
- Running scripted tests against Hot Module Replacement (HMR) during agent development.
|
|
9
|
+
|
|
10
|
+
## 1. Writing the Scenario (`scenarios/user-flow.scenario.ts`)
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
import { defineVisualTest, VIEWPORT_PRESETS } from 'agent-lens';
|
|
14
|
+
|
|
15
|
+
export default defineVisualTest({
|
|
16
|
+
id: 'user-registration-flow',
|
|
17
|
+
title: 'User Registration & Onboarding Flow',
|
|
18
|
+
route: '/register',
|
|
19
|
+
viewports: [VIEWPORT_PRESETS.DEFAULT, VIEWPORT_PRESETS.WIDE],
|
|
20
|
+
run: async (ctx) => {
|
|
21
|
+
// 1. Initial State
|
|
22
|
+
ctx.log('Checking registration form initial render');
|
|
23
|
+
await ctx.capture('01_register_empty');
|
|
24
|
+
|
|
25
|
+
// 2. Form Interaction
|
|
26
|
+
ctx.log('Filling registration inputs');
|
|
27
|
+
await ctx.type('input[name="email"]', 'agent@example.com');
|
|
28
|
+
await ctx.type('input[name="password"]', 'SecureP@ssw0rd!');
|
|
29
|
+
await ctx.click('input[type="checkbox"]');
|
|
30
|
+
await ctx.capture('02_register_filled');
|
|
31
|
+
|
|
32
|
+
// 3. Form Submission
|
|
33
|
+
await ctx.click('button[type="submit"]');
|
|
34
|
+
await ctx.waitForSelector('.welcome-banner', 5000);
|
|
35
|
+
await ctx.capture('03_onboarding_welcome');
|
|
36
|
+
|
|
37
|
+
// 4. Assertions
|
|
38
|
+
const welcomeText = await ctx.readText('.welcome-banner h1');
|
|
39
|
+
ctx.log(`Welcome banner title: "${welcomeText}"`);
|
|
40
|
+
|
|
41
|
+
const errors = ctx.getConsoleErrors();
|
|
42
|
+
if (errors.length > 0) {
|
|
43
|
+
ctx.log(`⚠️ Warning: Detected ${errors.length} console errors!`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 2. Running Against an Already Running Server
|
|
50
|
+
```bash
|
|
51
|
+
npx agent-lens --scenario=user-registration-flow --url=http://localhost:5173
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 3. Running with Managed Process Lifecycle
|
|
55
|
+
AgentLens launches `npm run dev`, waits for `http://localhost:5173` to be healthy, executes the scenario, and reliably shuts down the dev server process tree:
|
|
56
|
+
```bash
|
|
57
|
+
npx agent-lens \
|
|
58
|
+
--scenario=user-registration-flow \
|
|
59
|
+
--start="npm run dev" \
|
|
60
|
+
--url=http://localhost:5173 \
|
|
61
|
+
--folder=visual-reports
|
|
62
|
+
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Example 3: Component Isolation & Animation Bursts
|
|
2
|
+
|
|
3
|
+
Inspect single UI components without background clutter and capture frame-by-frame sequences of CSS/JS animations.
|
|
4
|
+
|
|
5
|
+
## Use Cases
|
|
6
|
+
- Verifying UI cards, tooltips, dropdown menus, and modal dialogs.
|
|
7
|
+
- Inspecting micro-interactions, fade-ins, and spring animations.
|
|
8
|
+
- Ensuring popups and dropdowns do not clip outside viewport bounds.
|
|
9
|
+
|
|
10
|
+
## Writing the Scenario (`scenarios/components.scenario.ts`)
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
import { defineVisualTest, VIEWPORT_PRESETS } from 'agent-lens';
|
|
14
|
+
|
|
15
|
+
export default defineVisualTest({
|
|
16
|
+
id: 'component-inspection',
|
|
17
|
+
title: 'Component Isolation & Micro-Interactions',
|
|
18
|
+
route: '/components',
|
|
19
|
+
run: async (ctx) => {
|
|
20
|
+
// 1. Dynamic Auto-Resize to Fit a Specific Component
|
|
21
|
+
ctx.log('Focusing strictly on the navigation navbar');
|
|
22
|
+
await ctx.resizeToFit('header.navbar', 10);
|
|
23
|
+
await ctx.capture('01_navbar_isolated');
|
|
24
|
+
|
|
25
|
+
// 2. Return to standard desktop dimensions
|
|
26
|
+
await ctx.setPreset(VIEWPORT_PRESETS.DEFAULT);
|
|
27
|
+
|
|
28
|
+
// 3. Hover Micro-Interaction with Burst Animation
|
|
29
|
+
ctx.log('Triggering dropdown menu hover animation');
|
|
30
|
+
await ctx.hover('.dropdown-trigger');
|
|
31
|
+
|
|
32
|
+
// Captures multiple consecutive frames over a 300ms duration at 50ms intervals
|
|
33
|
+
await ctx.captureBurst('02_dropdown_opening_animation', {
|
|
34
|
+
durationMs: 300,
|
|
35
|
+
intervalMs: 50,
|
|
36
|
+
selector: '.dropdown-menu'
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// 4. Final Stabilized State
|
|
40
|
+
await ctx.capture('03_dropdown_open_final', { selector: '.dropdown-menu' });
|
|
41
|
+
|
|
42
|
+
// 5. Scroll Interaction
|
|
43
|
+
ctx.log('Scrolling table down by 400px');
|
|
44
|
+
await ctx.scroll('.data-table-container', 400);
|
|
45
|
+
await ctx.capture('04_data_table_scrolled');
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Running the Scenario
|
|
51
|
+
```bash
|
|
52
|
+
npx agent-lens --scenario=component-inspection --url=http://localhost:5173
|
|
53
|
+
```
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Example 4: Native Desktop Application Testing (.exe / WebView2 / Electron)
|
|
2
|
+
|
|
3
|
+
Test real compiled native desktop binaries in production conditions, interacting with the real backend and rendering engine over Chrome DevTools Protocol (CDP).
|
|
4
|
+
|
|
5
|
+
## Use Cases
|
|
6
|
+
- Verifying desktop applications (Photino .NET, Electron, Tauri, WPF WebView2).
|
|
7
|
+
- Testing real system interactions, filesystem writes, and native process IPC.
|
|
8
|
+
- Verifying the app builds and boots up cleanly without missing DLLs or native crashes.
|
|
9
|
+
|
|
10
|
+
## 1. Writing the Scenario (`scenarios/desktop-app.scenario.ts`)
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
import { defineVisualTest, VIEWPORT_PRESETS } from 'agent-lens';
|
|
14
|
+
import fs from 'fs';
|
|
15
|
+
import path from 'path';
|
|
16
|
+
|
|
17
|
+
export default defineVisualTest({
|
|
18
|
+
id: 'desktop-smoke-test',
|
|
19
|
+
title: 'Native Desktop Application Production Verification',
|
|
20
|
+
run: async (ctx) => {
|
|
21
|
+
ctx.log('1. Waiting for native backend and UI initialization');
|
|
22
|
+
await ctx.wait(2500);
|
|
23
|
+
|
|
24
|
+
// Initial desktop screenshot
|
|
25
|
+
await ctx.setPreset(VIEWPORT_PRESETS.DEFAULT);
|
|
26
|
+
await ctx.capture('01_desktop_main_window');
|
|
27
|
+
|
|
28
|
+
// Test minimal window size constraints
|
|
29
|
+
await ctx.setPreset(VIEWPORT_PRESETS.MIN_SUPPORTED);
|
|
30
|
+
await ctx.capture('02_desktop_min_window');
|
|
31
|
+
await ctx.setPreset(VIEWPORT_PRESETS.DEFAULT);
|
|
32
|
+
|
|
33
|
+
// Click native action button that triggers backend work
|
|
34
|
+
ctx.log('2. Triggering native save action');
|
|
35
|
+
await ctx.click('button#save-preferences');
|
|
36
|
+
await ctx.wait(500);
|
|
37
|
+
await ctx.capture('03_saved_state');
|
|
38
|
+
|
|
39
|
+
// Verify file written to disk by real native backend
|
|
40
|
+
const savedConfig = path.resolve(process.cwd(), 'config', 'user-prefs.json');
|
|
41
|
+
if (fs.existsSync(savedConfig)) {
|
|
42
|
+
ctx.log('✅ Real backend successfully created config file on disk!');
|
|
43
|
+
} else {
|
|
44
|
+
ctx.log('⚠️ Config file was not written to disk.');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 2. Running with Automated Build and Binary Launch
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npx agent-lens \
|
|
54
|
+
--scenario=desktop-smoke-test \
|
|
55
|
+
--mode=desktop \
|
|
56
|
+
--build="dotnet build -c Release" \
|
|
57
|
+
--exe="bin/Release/net8.0-windows/MyApp.exe" \
|
|
58
|
+
--port=9222 \
|
|
59
|
+
--folder=visual-reports
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### How AgentLens Handles Native Apps:
|
|
63
|
+
1. Runs the specified build command (`--build`).
|
|
64
|
+
2. Spawns `MyApp.exe` with remote debugging flags.
|
|
65
|
+
3. If the executable crashes on launch (e.g. missing runtime, segfault), AgentLens immediately catches the exit code and stderr, printing the exact crash log.
|
|
66
|
+
4. Once the CDP port is listening, Playwright attaches directly to the native window.
|
|
67
|
+
5. Runs the test and takes snapshots.
|
|
68
|
+
6. Gracefully terminates the process tree on completion.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Example 5: Clean Teardown & Auto-Cleanup Lifecycle
|
|
2
|
+
|
|
3
|
+
Prevent test pollution, corrupted databases, and "buggy" leftover artifacts when running end-to-end tests.
|
|
4
|
+
|
|
5
|
+
## The Problem
|
|
6
|
+
When testing actions like "Create Project", "Download Asset", or "Save Profile", test artifacts are created on the real filesystem. If the test crashes halfway, corrupted files remain, causing future test runs to fail mysteriously.
|
|
7
|
+
|
|
8
|
+
## The Solution
|
|
9
|
+
AgentLens provides two lines of defense:
|
|
10
|
+
1. **`teardown()` hook**: Guaranteed to execute in a `finally` block, even if the scenario throws an uncaught error.
|
|
11
|
+
2. **`--clean=<paths>` CLI flag**: Automatically deletes specified folders or files after the test completes.
|
|
12
|
+
|
|
13
|
+
## Writing the Scenario (`scenarios/isolated-data.scenario.ts`)
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { defineVisualTest } from 'agent-lens';
|
|
17
|
+
import fs from 'fs';
|
|
18
|
+
import path from 'path';
|
|
19
|
+
|
|
20
|
+
const TEST_SANDBOX_DIR = path.resolve(process.cwd(), '.tmp_test_sandbox');
|
|
21
|
+
|
|
22
|
+
export default defineVisualTest({
|
|
23
|
+
id: 'isolated-creation-flow',
|
|
24
|
+
title: 'Data Creation with Guaranteed Cleanup',
|
|
25
|
+
route: '/projects',
|
|
26
|
+
|
|
27
|
+
// 1. Setup: Prepare a clean workspace before testing begins
|
|
28
|
+
setup: async () => {
|
|
29
|
+
if (fs.existsSync(TEST_SANDBOX_DIR)) {
|
|
30
|
+
fs.rmSync(TEST_SANDBOX_DIR, { recursive: true, force: true });
|
|
31
|
+
}
|
|
32
|
+
fs.mkdirSync(TEST_SANDBOX_DIR, { recursive: true });
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
// 2. Main Test Run
|
|
36
|
+
run: async (ctx) => {
|
|
37
|
+
ctx.log('Creating a new test project');
|
|
38
|
+
await ctx.click('button#new-project');
|
|
39
|
+
await ctx.type('input#project-name', 'Temporary_Test_Project');
|
|
40
|
+
await ctx.click('button#confirm');
|
|
41
|
+
|
|
42
|
+
await ctx.wait(800);
|
|
43
|
+
await ctx.capture('01_project_created');
|
|
44
|
+
|
|
45
|
+
// Perform verification assertions
|
|
46
|
+
const count = await ctx.getElementCount('.project-item');
|
|
47
|
+
ctx.log(`Current project count: ${count}`);
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
// 3. Teardown: ALWAYS executes, even if run() fails!
|
|
51
|
+
teardown: async () => {
|
|
52
|
+
console.log('[Teardown] Purging sandbox test directory');
|
|
53
|
+
if (fs.existsSync(TEST_SANDBOX_DIR)) {
|
|
54
|
+
fs.rmSync(TEST_SANDBOX_DIR, { recursive: true, force: true });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Running with Auto-Cleanup Flags
|
|
61
|
+
|
|
62
|
+
You can also pass additional paths to clean up directly from the CLI:
|
|
63
|
+
```bash
|
|
64
|
+
npx agent-lens \
|
|
65
|
+
--scenario=isolated-creation-flow \
|
|
66
|
+
--clean="./cache,./tmp_data,.tmp_test_sandbox"
|
|
67
|
+
```
|
|
68
|
+
AgentLens ensures all specified targets are purged on completion.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Example 6: State Testing with Mock IPC
|
|
2
|
+
|
|
3
|
+
Simulate different application states (empty list, loading spinners, network errors, populated data) without running a real backend.
|
|
4
|
+
|
|
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.
|
|
9
|
+
|
|
10
|
+
## Writing the Scenario (`scenarios/states.scenario.ts`)
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
import { defineVisualTest, VIEWPORT_PRESETS } from 'agent-lens';
|
|
14
|
+
|
|
15
|
+
export default defineVisualTest({
|
|
16
|
+
id: 'ui-state-verification',
|
|
17
|
+
title: 'Empty State vs Populated State Verification',
|
|
18
|
+
route: '/users',
|
|
19
|
+
|
|
20
|
+
// 1. Initial State: Populated list
|
|
21
|
+
mockIpc: [
|
|
22
|
+
{
|
|
23
|
+
action: 'GET_USERS',
|
|
24
|
+
data: [
|
|
25
|
+
{ id: 1, name: 'Alice Cooper', role: 'Administrator' },
|
|
26
|
+
{ id: 2, name: 'Bob Marley', role: 'Editor' }
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
|
|
31
|
+
run: async (ctx) => {
|
|
32
|
+
// Check populated table
|
|
33
|
+
ctx.log('1. Checking populated users table');
|
|
34
|
+
await ctx.capture('01_users_populated');
|
|
35
|
+
|
|
36
|
+
// 2. Dynamically swap mock data to Empty State during the test
|
|
37
|
+
ctx.log('2. Updating mock to empty list');
|
|
38
|
+
await ctx.setMockIpc('GET_USERS', []);
|
|
39
|
+
|
|
40
|
+
// Re-navigate or trigger refresh
|
|
41
|
+
await ctx.navigate('/users');
|
|
42
|
+
await ctx.wait(300);
|
|
43
|
+
await ctx.capture('02_users_empty_state');
|
|
44
|
+
|
|
45
|
+
// Verify empty state message in DOM
|
|
46
|
+
const hasEmptyMessage = await ctx.isVisible('text="No users found"');
|
|
47
|
+
ctx.log(`Empty state text visible: ${hasEmptyMessage}`);
|
|
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' });
|
|
52
|
+
await ctx.navigate('/users');
|
|
53
|
+
await ctx.wait(300);
|
|
54
|
+
await ctx.capture('03_users_error_state');
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Running the Scenario
|
|
60
|
+
```bash
|
|
61
|
+
npx agent-lens --scenario=ui-state-verification --mode=preview
|
|
62
|
+
```
|