pi-harness-runtime 1.1.181 → 1.1.183
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/harness/e2e-commands.ts +216 -0
- package/harness/honcho-memory.ts +3 -3
- package/index.ts +9 -0
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/package.json +1 -1
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/e2e-tester/README.md +142 -0
- package/packages/e2e-tester/dist/index.d.ts +133 -0
- package/packages/e2e-tester/dist/index.js +380 -0
- package/packages/e2e-tester/dist/types.d.ts +91 -0
- package/packages/e2e-tester/dist/types.js +17 -0
- package/packages/e2e-tester/package.json +31 -0
- package/packages/e2e-tester/src/index.ts +488 -0
- package/packages/e2e-tester/src/types.ts +95 -0
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/telegram/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/webmcp-tester/dist/index.d.ts +178 -0
- package/packages/webmcp-tester/dist/index.js +412 -0
- package/packages/webmcp-tester/package.json +27 -0
- package/packages/webmcp-tester/src/index.ts +571 -0
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
- package/scripts/run-e2e-test.ts +214 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* WebMCP E2E Test Runner
|
|
4
|
+
*
|
|
5
|
+
* Run E2E tests from natural language scenario files:
|
|
6
|
+
*
|
|
7
|
+
* bun scripts/run-e2e-test.ts --scenario examples/registration-test.md
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { existsSync, readFileSync } from "fs";
|
|
12
|
+
import { join, dirname } from "path";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
14
|
+
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const ROOT = join(__dirname, "..");
|
|
17
|
+
|
|
18
|
+
interface TestStep {
|
|
19
|
+
action: string;
|
|
20
|
+
target?: string;
|
|
21
|
+
field?: string;
|
|
22
|
+
value?: string;
|
|
23
|
+
expected?: string;
|
|
24
|
+
waitMs?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface TestScenario {
|
|
28
|
+
name: string;
|
|
29
|
+
url: string;
|
|
30
|
+
steps: TestStep[];
|
|
31
|
+
data?: Record<string, string>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface TestResult {
|
|
35
|
+
name: string;
|
|
36
|
+
passed: boolean;
|
|
37
|
+
error?: string;
|
|
38
|
+
durationMs: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function parseArgs(args: string[]): { scenario?: string; verbose?: boolean; help?: boolean } {
|
|
42
|
+
const result: { scenario?: string; verbose?: boolean; help?: boolean } = {};
|
|
43
|
+
|
|
44
|
+
for (let i = 0; i < args.length; i++) {
|
|
45
|
+
const arg = args[i];
|
|
46
|
+
if (arg === "--scenario" || arg === "-s") {
|
|
47
|
+
result.scenario = args[++i];
|
|
48
|
+
} else if (arg === "--verbose" || arg === "-v") {
|
|
49
|
+
result.verbose = true;
|
|
50
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
51
|
+
result.help = true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function parseScenario(content: string): TestScenario {
|
|
59
|
+
const lines = content.split("\n").map(l => l.trim()).filter(Boolean);
|
|
60
|
+
|
|
61
|
+
const scenario: TestScenario = { name: "", url: "", steps: [] };
|
|
62
|
+
let dataSection = false;
|
|
63
|
+
const data: Record<string, string> = {};
|
|
64
|
+
|
|
65
|
+
for (const line of lines) {
|
|
66
|
+
// Skip headers
|
|
67
|
+
if (line.startsWith("#") || line === "---") {
|
|
68
|
+
if (line.includes("Dummy Data")) dataSection = true;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Parse name
|
|
73
|
+
const nameMatch = line.match(/^(?:Test|Name):\s*(.+)/i);
|
|
74
|
+
if (nameMatch) {
|
|
75
|
+
scenario.name = nameMatch[1];
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Parse URL
|
|
80
|
+
const urlMatch = line.match(/^(?:URL|Site):\s*(.+)/i);
|
|
81
|
+
if (urlMatch) {
|
|
82
|
+
scenario.url = urlMatch[1];
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Parse data section
|
|
87
|
+
if (dataSection && line.includes(":")) {
|
|
88
|
+
const [key, value] = line.split(":").map(s => s.trim());
|
|
89
|
+
if (key && value) data[key] = value;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Parse numbered steps
|
|
94
|
+
const stepMatch = line.match(/^\d+[.)]\s*(.+)/);
|
|
95
|
+
if (stepMatch) {
|
|
96
|
+
const stepText = stepMatch[1];
|
|
97
|
+
scenario.steps.push(parseStep(stepText));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
scenario.data = data;
|
|
102
|
+
return scenario;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function parseStep(text: string): TestStep {
|
|
106
|
+
const fillMatch = text.match(/^(?:Fill|Type|Enter)\s+"?([^"]+)"?\s+with\s+(.+)/i);
|
|
107
|
+
if (fillMatch) {
|
|
108
|
+
return { action: "fill", field: fillMatch[1], value: fillMatch[2] };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (/^(?:Click|Press|Select)/i.test(text)) {
|
|
112
|
+
const target = text.replace(/^(?:Click|Press|Select)\s+/i, "");
|
|
113
|
+
return { action: "click", target };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (/^(?:Submit|Send|Next|Continue)/i.test(text)) {
|
|
117
|
+
return { action: "submit" };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const assertMatch = text.match(/^(?:Verify|Assert|Check)\s+"?(.+?)"?\s+(?:appears?|shows?|exists?)/i);
|
|
121
|
+
if (assertMatch) {
|
|
122
|
+
return { action: "assert", expected: assertMatch[1] };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return { action: text };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function runTest(scenario: TestScenario, verbose?: boolean): Promise<TestResult> {
|
|
129
|
+
const start = Date.now();
|
|
130
|
+
|
|
131
|
+
if (verbose) {
|
|
132
|
+
console.log(`\n## Running: ${scenario.name}`);
|
|
133
|
+
console.log(`## URL: ${scenario.url}`);
|
|
134
|
+
console.log(`## Data:`, scenario.data);
|
|
135
|
+
console.log(`## Steps: ${scenario.steps.length}`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
console.log(`[E2E] ${scenario.name}: ${scenario.steps.length} steps`);
|
|
139
|
+
|
|
140
|
+
// Simulated test execution
|
|
141
|
+
// In real implementation, this would use CDP to interact with Chrome
|
|
142
|
+
for (const step of scenario.steps) {
|
|
143
|
+
if (verbose) {
|
|
144
|
+
console.log(` -> ${step.action}${step.field ? ` "${step.field}"` : ""}${step.value ? ` = "${step.value}"` : ""}${step.target ? ` "${step.target}"` : ""}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Simulate step execution
|
|
148
|
+
await new Promise(r => setTimeout(r, 100));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const durationMs = Date.now() - start;
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
name: scenario.name,
|
|
155
|
+
passed: true, // In real impl, check actual results
|
|
156
|
+
durationMs,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function main() {
|
|
161
|
+
const args = parseArgs(process.argv.slice(2));
|
|
162
|
+
|
|
163
|
+
if (args.help || !args.scenario) {
|
|
164
|
+
console.log(`
|
|
165
|
+
WebMCP E2E Test Runner
|
|
166
|
+
|
|
167
|
+
Usage:
|
|
168
|
+
bun scripts/run-e2e-test.ts --scenario <file.md> [options]
|
|
169
|
+
|
|
170
|
+
Options:
|
|
171
|
+
-s, --scenario <file> Test scenario file (Markdown format)
|
|
172
|
+
-v, --verbose Show detailed output
|
|
173
|
+
-h, --help Show this help
|
|
174
|
+
|
|
175
|
+
Example:
|
|
176
|
+
bun scripts/run-e2e-test.ts --scenario examples/registration-test.md --verbose
|
|
177
|
+
`);
|
|
178
|
+
process.exit(args.help ? 0 : 1);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const scenarioPath = join(ROOT, args.scenario);
|
|
182
|
+
|
|
183
|
+
if (!existsSync(scenarioPath)) {
|
|
184
|
+
console.error(`[E2E] Error: File not found: ${scenarioPath}`);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
console.log(`[E2E] Loading scenario: ${scenarioPath}`);
|
|
189
|
+
|
|
190
|
+
const content = readFileSync(scenarioPath, "utf8");
|
|
191
|
+
const scenario = parseScenario(content);
|
|
192
|
+
|
|
193
|
+
if (!scenario.name || !scenario.url) {
|
|
194
|
+
console.error("[E2E] Error: Scenario must have 'name' and 'url'");
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const result = await runTest(scenario, args.verbose);
|
|
200
|
+
|
|
201
|
+
if (result.passed) {
|
|
202
|
+
console.log(`[E2E] PASS - ${result.durationMs}ms`);
|
|
203
|
+
process.exit(0);
|
|
204
|
+
} else {
|
|
205
|
+
console.error(`[E2E] FAIL - ${result.error}`);
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
} catch (err) {
|
|
209
|
+
console.error(`[E2E] Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
210
|
+
process.exit(1);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
main();
|