cbrowser 6.3.2 → 6.5.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/daemon.js ADDED
@@ -0,0 +1,358 @@
1
+ "use strict";
2
+ /**
3
+ * CBrowser Daemon Mode
4
+ *
5
+ * Keeps browser running between CLI commands for faster iteration.
6
+ *
7
+ * Usage:
8
+ * cbrowser daemon start # Start daemon in background
9
+ * cbrowser daemon stop # Stop daemon
10
+ * cbrowser daemon status # Check if daemon is running
11
+ *
12
+ * Once running, all other commands automatically connect to the daemon
13
+ * instead of launching a new browser.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.getDaemonState = getDaemonState;
17
+ exports.isDaemonRunning = isDaemonRunning;
18
+ exports.sendToDaemon = sendToDaemon;
19
+ exports.startDaemon = startDaemon;
20
+ exports.stopDaemon = stopDaemon;
21
+ exports.getDaemonStatus = getDaemonStatus;
22
+ exports.runDaemonServer = runDaemonServer;
23
+ const http_1 = require("http");
24
+ const fs_1 = require("fs");
25
+ const path_1 = require("path");
26
+ const child_process_1 = require("child_process");
27
+ const browser_js_1 = require("./browser.js");
28
+ const config_js_1 = require("./config.js");
29
+ const DEFAULT_PORT = 9222;
30
+ const DAEMON_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes idle timeout
31
+ /**
32
+ * Get the daemon state file path
33
+ */
34
+ function getDaemonStatePath() {
35
+ const paths = (0, config_js_1.getPaths)();
36
+ return (0, path_1.join)(paths.dataDir, "daemon.json");
37
+ }
38
+ /**
39
+ * Get the daemon log file path
40
+ */
41
+ function getDaemonLogPath() {
42
+ const paths = (0, config_js_1.getPaths)();
43
+ return (0, path_1.join)(paths.dataDir, "daemon.log");
44
+ }
45
+ /**
46
+ * Read daemon state from disk
47
+ */
48
+ function getDaemonState() {
49
+ const statePath = getDaemonStatePath();
50
+ if (!(0, fs_1.existsSync)(statePath)) {
51
+ return null;
52
+ }
53
+ try {
54
+ const data = (0, fs_1.readFileSync)(statePath, "utf-8");
55
+ return JSON.parse(data);
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ }
61
+ /**
62
+ * Write daemon state to disk
63
+ */
64
+ function writeDaemonState(state) {
65
+ const statePath = getDaemonStatePath();
66
+ (0, fs_1.writeFileSync)(statePath, JSON.stringify(state, null, 2));
67
+ }
68
+ /**
69
+ * Clear daemon state file
70
+ */
71
+ function clearDaemonState() {
72
+ const statePath = getDaemonStatePath();
73
+ if ((0, fs_1.existsSync)(statePath)) {
74
+ (0, fs_1.unlinkSync)(statePath);
75
+ }
76
+ }
77
+ /**
78
+ * Check if daemon is running
79
+ */
80
+ async function isDaemonRunning() {
81
+ const state = getDaemonState();
82
+ if (!state) {
83
+ return false;
84
+ }
85
+ // Try to ping the daemon
86
+ try {
87
+ const response = await fetch(`http://127.0.0.1:${state.port}/ping`, {
88
+ method: "GET",
89
+ signal: AbortSignal.timeout(1000),
90
+ });
91
+ return response.ok;
92
+ }
93
+ catch {
94
+ // Daemon not responding, clean up stale state
95
+ clearDaemonState();
96
+ return false;
97
+ }
98
+ }
99
+ /**
100
+ * Send a command to the running daemon
101
+ */
102
+ async function sendToDaemon(command, args = {}) {
103
+ const state = getDaemonState();
104
+ if (!state) {
105
+ return { success: false, error: "Daemon not running" };
106
+ }
107
+ try {
108
+ const response = await fetch(`http://127.0.0.1:${state.port}/command`, {
109
+ method: "POST",
110
+ headers: { "Content-Type": "application/json" },
111
+ body: JSON.stringify({ command, args }),
112
+ signal: AbortSignal.timeout(120000), // 2 minute timeout for commands
113
+ });
114
+ const data = await response.json();
115
+ return data;
116
+ }
117
+ catch (err) {
118
+ return { success: false, error: `Failed to communicate with daemon: ${err}` };
119
+ }
120
+ }
121
+ /**
122
+ * Start the daemon in the background
123
+ */
124
+ async function startDaemon(port = DEFAULT_PORT) {
125
+ // Check if already running
126
+ if (await isDaemonRunning()) {
127
+ const state = getDaemonState();
128
+ return { success: true, message: `Daemon already running on port ${state.port} (PID: ${state.pid})` };
129
+ }
130
+ // Start daemon as background process
131
+ const logPath = getDaemonLogPath();
132
+ const child = (0, child_process_1.spawn)(process.execPath, [process.argv[1], "daemon", "run", "--port", String(port)], {
133
+ detached: true,
134
+ stdio: ["ignore", "pipe", "pipe"],
135
+ });
136
+ // Write logs to file
137
+ const logStream = require("fs").createWriteStream(logPath, { flags: "a" });
138
+ child.stdout?.pipe(logStream);
139
+ child.stderr?.pipe(logStream);
140
+ child.unref();
141
+ // Wait for daemon to be ready
142
+ const maxWait = 10000;
143
+ const startTime = Date.now();
144
+ while (Date.now() - startTime < maxWait) {
145
+ await new Promise(resolve => setTimeout(resolve, 200));
146
+ if (await isDaemonRunning()) {
147
+ const state = getDaemonState();
148
+ return { success: true, message: `Daemon started on port ${state.port} (PID: ${state.pid})` };
149
+ }
150
+ }
151
+ return { success: false, message: "Daemon failed to start within 10 seconds" };
152
+ }
153
+ /**
154
+ * Stop the running daemon
155
+ */
156
+ async function stopDaemon() {
157
+ const state = getDaemonState();
158
+ if (!state) {
159
+ return { success: true, message: "Daemon not running" };
160
+ }
161
+ try {
162
+ // Send shutdown command
163
+ await fetch(`http://127.0.0.1:${state.port}/shutdown`, {
164
+ method: "POST",
165
+ signal: AbortSignal.timeout(5000),
166
+ }).catch(() => { });
167
+ // Wait for daemon to stop
168
+ await new Promise(resolve => setTimeout(resolve, 500));
169
+ // Force kill if still running
170
+ try {
171
+ process.kill(state.pid, 0); // Check if process exists
172
+ process.kill(state.pid, "SIGTERM");
173
+ }
174
+ catch {
175
+ // Process already gone
176
+ }
177
+ clearDaemonState();
178
+ return { success: true, message: `Daemon stopped (was PID: ${state.pid})` };
179
+ }
180
+ catch (err) {
181
+ clearDaemonState();
182
+ return { success: true, message: `Daemon stopped (cleanup: ${err})` };
183
+ }
184
+ }
185
+ /**
186
+ * Get daemon status
187
+ */
188
+ async function getDaemonStatus() {
189
+ const running = await isDaemonRunning();
190
+ const state = getDaemonState();
191
+ if (!running || !state) {
192
+ return "Daemon is not running";
193
+ }
194
+ const uptime = Math.round((Date.now() - new Date(state.startedAt).getTime()) / 1000);
195
+ const lastActivity = Math.round((Date.now() - new Date(state.lastActivity).getTime()) / 1000);
196
+ return `Daemon running:
197
+ PID: ${state.pid}
198
+ Port: ${state.port}
199
+ Uptime: ${uptime}s
200
+ Last activity: ${lastActivity}s ago`;
201
+ }
202
+ /**
203
+ * Run the daemon server (called in foreground mode)
204
+ */
205
+ async function runDaemonServer(config, port = DEFAULT_PORT) {
206
+ let browser = null;
207
+ let idleTimer = null;
208
+ let lastActivity = new Date();
209
+ const resetIdleTimer = () => {
210
+ lastActivity = new Date();
211
+ if (idleTimer) {
212
+ clearTimeout(idleTimer);
213
+ }
214
+ idleTimer = setTimeout(async () => {
215
+ console.log(`[${new Date().toISOString()}] Daemon idle timeout, shutting down...`);
216
+ await shutdown();
217
+ }, DAEMON_TIMEOUT_MS);
218
+ };
219
+ const updateState = () => {
220
+ const state = getDaemonState();
221
+ if (state) {
222
+ state.lastActivity = lastActivity.toISOString();
223
+ writeDaemonState(state);
224
+ }
225
+ };
226
+ const getBrowser = async () => {
227
+ if (!browser) {
228
+ const fullConfig = (0, config_js_1.mergeConfig)({ ...config, persistent: true });
229
+ browser = new browser_js_1.CBrowser(fullConfig);
230
+ }
231
+ return browser;
232
+ };
233
+ const handleCommand = async (req) => {
234
+ resetIdleTimer();
235
+ updateState();
236
+ try {
237
+ const b = await getBrowser();
238
+ switch (req.command) {
239
+ case "navigate": {
240
+ const url = req.args.url;
241
+ const result = await b.navigate(url);
242
+ return { success: true, result };
243
+ }
244
+ case "click": {
245
+ const selector = req.args.selector;
246
+ const result = await b.click(selector);
247
+ return { success: true, result };
248
+ }
249
+ case "fill": {
250
+ const selector = req.args.selector;
251
+ const value = req.args.value;
252
+ const result = await b.fill(selector, value);
253
+ return { success: true, result };
254
+ }
255
+ case "screenshot": {
256
+ const path = req.args.path;
257
+ const result = await b.screenshot(path);
258
+ return { success: true, result };
259
+ }
260
+ case "extract": {
261
+ const what = req.args.what;
262
+ const result = await b.extract(what);
263
+ return { success: true, result };
264
+ }
265
+ case "run": {
266
+ const command = req.args.command;
267
+ const result = await (0, browser_js_1.executeNaturalLanguage)(b, command);
268
+ return { success: true, result };
269
+ }
270
+ case "getPage": {
271
+ // Navigate to about:blank to ensure page is loaded, then get info
272
+ const navResult = await b.navigate("about:blank");
273
+ return {
274
+ success: true,
275
+ result: {
276
+ url: navResult.url,
277
+ title: navResult.title,
278
+ },
279
+ };
280
+ }
281
+ default:
282
+ return { success: false, error: `Unknown command: ${req.command}` };
283
+ }
284
+ }
285
+ catch (err) {
286
+ return { success: false, error: String(err) };
287
+ }
288
+ };
289
+ const server = (0, http_1.createServer)(async (req, res) => {
290
+ // CORS headers
291
+ res.setHeader("Access-Control-Allow-Origin", "*");
292
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
293
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
294
+ if (req.method === "OPTIONS") {
295
+ res.writeHead(204);
296
+ res.end();
297
+ return;
298
+ }
299
+ if (req.url === "/ping" && req.method === "GET") {
300
+ res.writeHead(200, { "Content-Type": "application/json" });
301
+ res.end(JSON.stringify({ status: "ok", uptime: process.uptime() }));
302
+ return;
303
+ }
304
+ if (req.url === "/shutdown" && req.method === "POST") {
305
+ res.writeHead(200, { "Content-Type": "application/json" });
306
+ res.end(JSON.stringify({ status: "shutting down" }));
307
+ await shutdown();
308
+ return;
309
+ }
310
+ if (req.url === "/command" && req.method === "POST") {
311
+ let body = "";
312
+ req.on("data", chunk => { body += chunk; });
313
+ req.on("end", async () => {
314
+ try {
315
+ const request = JSON.parse(body);
316
+ const response = await handleCommand(request);
317
+ res.writeHead(200, { "Content-Type": "application/json" });
318
+ res.end(JSON.stringify(response));
319
+ }
320
+ catch (err) {
321
+ res.writeHead(400, { "Content-Type": "application/json" });
322
+ res.end(JSON.stringify({ success: false, error: `Invalid request: ${err}` }));
323
+ }
324
+ });
325
+ return;
326
+ }
327
+ res.writeHead(404, { "Content-Type": "application/json" });
328
+ res.end(JSON.stringify({ error: "Not found" }));
329
+ });
330
+ const shutdown = async () => {
331
+ if (idleTimer) {
332
+ clearTimeout(idleTimer);
333
+ }
334
+ if (browser) {
335
+ await browser.close();
336
+ }
337
+ server.close();
338
+ clearDaemonState();
339
+ process.exit(0);
340
+ };
341
+ // Handle termination signals
342
+ process.on("SIGTERM", shutdown);
343
+ process.on("SIGINT", shutdown);
344
+ // Start server
345
+ server.listen(port, "127.0.0.1", () => {
346
+ const state = {
347
+ pid: process.pid,
348
+ port,
349
+ startedAt: new Date().toISOString(),
350
+ lastActivity: new Date().toISOString(),
351
+ };
352
+ writeDaemonState(state);
353
+ console.log(`[${new Date().toISOString()}] CBrowser daemon started on port ${port} (PID: ${process.pid})`);
354
+ console.log(`[${new Date().toISOString()}] Idle timeout: ${DAEMON_TIMEOUT_MS / 1000 / 60} minutes`);
355
+ resetIdleTimer();
356
+ });
357
+ }
358
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -17,4 +17,5 @@ export type { CBrowserConfig, CBrowserPaths, BrowserType } from "./config.js";
17
17
  export * from "./types.js";
18
18
  export { BUILTIN_PERSONAS } from "./personas.js";
19
19
  export { startMcpServer } from "./mcp-server.js";
20
+ export { startDaemon, stopDaemon, getDaemonStatus, isDaemonRunning, sendToDaemon, runDaemonServer } from "./daemon.js";
20
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzF,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC9E,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzF,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC9E,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
27
27
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
28
28
  };
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
- exports.startMcpServer = exports.BUILTIN_PERSONAS = exports.mergeConfig = exports.ensureDirectories = exports.getPaths = exports.getDefaultConfig = exports.CBrowser = void 0;
30
+ exports.runDaemonServer = exports.sendToDaemon = exports.isDaemonRunning = exports.getDaemonStatus = exports.stopDaemon = exports.startDaemon = exports.startMcpServer = exports.BUILTIN_PERSONAS = exports.mergeConfig = exports.ensureDirectories = exports.getPaths = exports.getDefaultConfig = exports.CBrowser = void 0;
31
31
  var browser_js_1 = require("./browser.js");
32
32
  Object.defineProperty(exports, "CBrowser", { enumerable: true, get: function () { return browser_js_1.CBrowser; } });
33
33
  var config_js_1 = require("./config.js");
@@ -40,4 +40,11 @@ var personas_js_1 = require("./personas.js");
40
40
  Object.defineProperty(exports, "BUILTIN_PERSONAS", { enumerable: true, get: function () { return personas_js_1.BUILTIN_PERSONAS; } });
41
41
  var mcp_server_js_1 = require("./mcp-server.js");
42
42
  Object.defineProperty(exports, "startMcpServer", { enumerable: true, get: function () { return mcp_server_js_1.startMcpServer; } });
43
+ var daemon_js_1 = require("./daemon.js");
44
+ Object.defineProperty(exports, "startDaemon", { enumerable: true, get: function () { return daemon_js_1.startDaemon; } });
45
+ Object.defineProperty(exports, "stopDaemon", { enumerable: true, get: function () { return daemon_js_1.stopDaemon; } });
46
+ Object.defineProperty(exports, "getDaemonStatus", { enumerable: true, get: function () { return daemon_js_1.getDaemonStatus; } });
47
+ Object.defineProperty(exports, "isDaemonRunning", { enumerable: true, get: function () { return daemon_js_1.isDaemonRunning; } });
48
+ Object.defineProperty(exports, "sendToDaemon", { enumerable: true, get: function () { return daemon_js_1.sendToDaemon; } });
49
+ Object.defineProperty(exports, "runDaemonServer", { enumerable: true, get: function () { return daemon_js_1.runDaemonServer; } });
43
50
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;;;;;;;;;;;;;;;AAEH,2CAAwC;AAA/B,sGAAA,QAAQ,OAAA;AACjB,yCAAyF;AAAhF,6GAAA,gBAAgB,OAAA;AAAE,qGAAA,QAAQ,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AAAE,wGAAA,WAAW,OAAA;AAEnE,6CAA2B;AAC3B,6CAAiD;AAAxC,+GAAA,gBAAgB,OAAA;AACzB,iDAAiD;AAAxC,+GAAA,cAAc,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;;;;;;;;;;;;;;;AAEH,2CAAwC;AAA/B,sGAAA,QAAQ,OAAA;AACjB,yCAAyF;AAAhF,6GAAA,gBAAgB,OAAA;AAAE,qGAAA,QAAQ,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AAAE,wGAAA,WAAW,OAAA;AAEnE,6CAA2B;AAC3B,6CAAiD;AAAxC,+GAAA,gBAAgB,OAAA;AACzB,iDAAiD;AAAxC,+GAAA,cAAc,OAAA;AACvB,yCAAuH;AAA9G,wGAAA,WAAW,OAAA;AAAE,uGAAA,UAAU,OAAA;AAAE,4GAAA,eAAe,OAAA;AAAE,4GAAA,eAAe,OAAA;AAAE,yGAAA,YAAY,OAAA;AAAE,4GAAA,eAAe,OAAA"}
package/dist/types.d.ts CHANGED
@@ -810,4 +810,213 @@ export interface TestGenerationResult {
810
810
  cbrowserScript: string;
811
811
  playwrightCode: string;
812
812
  }
813
+ export interface PerformanceBaseline {
814
+ /** Unique identifier for this baseline */
815
+ id: string;
816
+ /** URL this baseline was captured from */
817
+ url: string;
818
+ /** Human-readable name for this baseline */
819
+ name: string;
820
+ /** Timestamp when baseline was captured */
821
+ timestamp: string;
822
+ /** Performance metrics captured */
823
+ metrics: PerformanceMetrics;
824
+ /** Number of runs averaged (for stability) */
825
+ runsAveraged: number;
826
+ /** Environment info */
827
+ environment: {
828
+ browser: string;
829
+ viewport: {
830
+ width: number;
831
+ height: number;
832
+ };
833
+ device?: string;
834
+ connection?: string;
835
+ };
836
+ }
837
+ export interface PerformanceRegressionThresholds {
838
+ /** Max allowed increase in LCP (percentage, default: 20) */
839
+ lcp?: number;
840
+ /** Max allowed increase in FID (percentage, default: 50) */
841
+ fid?: number;
842
+ /** Max allowed increase in CLS (absolute, default: 0.1) */
843
+ cls?: number;
844
+ /** Max allowed increase in FCP (percentage, default: 20) */
845
+ fcp?: number;
846
+ /** Max allowed increase in TTFB (percentage, default: 30) */
847
+ ttfb?: number;
848
+ /** Max allowed increase in TTI (percentage, default: 25) */
849
+ tti?: number;
850
+ /** Max allowed increase in TBT (percentage, default: 50) */
851
+ tbt?: number;
852
+ /** Max allowed increase in transfer size (percentage, default: 25) */
853
+ transferSize?: number;
854
+ }
855
+ export interface MetricRegression {
856
+ /** Metric name */
857
+ metric: keyof PerformanceMetrics;
858
+ /** Baseline value */
859
+ baselineValue: number;
860
+ /** Current value */
861
+ currentValue: number;
862
+ /** Change amount */
863
+ change: number;
864
+ /** Change percentage */
865
+ changePercent: number;
866
+ /** Threshold that was exceeded */
867
+ threshold: number;
868
+ /** Severity of regression */
869
+ severity: "warning" | "regression" | "critical";
870
+ }
871
+ export interface PerformanceComparison {
872
+ /** Metric name */
873
+ metric: keyof PerformanceMetrics;
874
+ /** Baseline value */
875
+ baseline: number;
876
+ /** Current value */
877
+ current: number;
878
+ /** Change amount (positive = worse, negative = better) */
879
+ change: number;
880
+ /** Change percentage */
881
+ changePercent: number;
882
+ /** Is this a regression? */
883
+ isRegression: boolean;
884
+ /** Is this an improvement? */
885
+ isImprovement: boolean;
886
+ /** Status indicator */
887
+ status: "improved" | "stable" | "warning" | "regression" | "critical";
888
+ }
889
+ export interface PerformanceRegressionResult {
890
+ /** URL tested */
891
+ url: string;
892
+ /** Baseline used for comparison */
893
+ baseline: PerformanceBaseline;
894
+ /** Current metrics */
895
+ currentMetrics: PerformanceMetrics;
896
+ /** Timestamp of this test */
897
+ timestamp: string;
898
+ /** Duration of test */
899
+ duration: number;
900
+ /** Detailed comparison per metric */
901
+ comparisons: PerformanceComparison[];
902
+ /** Detected regressions */
903
+ regressions: MetricRegression[];
904
+ /** Overall result */
905
+ passed: boolean;
906
+ /** Summary */
907
+ summary: {
908
+ totalMetrics: number;
909
+ improved: number;
910
+ stable: number;
911
+ regressed: number;
912
+ critical: number;
913
+ overallChange: number;
914
+ };
915
+ }
916
+ export interface TestedPage {
917
+ /** URL or route pattern */
918
+ url: string;
919
+ /** Normalized path for matching */
920
+ path: string;
921
+ /** Test files that cover this page */
922
+ testFiles: string[];
923
+ /** Actions tested on this page */
924
+ actions: TestedAction[];
925
+ /** Number of test cases covering this page */
926
+ testCount: number;
927
+ /** Coverage score (0-100) */
928
+ coverageScore: number;
929
+ }
930
+ export interface TestedAction {
931
+ /** Action type */
932
+ type: "navigate" | "click" | "fill" | "verify" | "wait" | "scroll" | "hover";
933
+ /** Target element description */
934
+ target?: string;
935
+ /** Value if applicable */
936
+ value?: string;
937
+ /** Test file containing this action */
938
+ testFile: string;
939
+ /** Line number in test file */
940
+ lineNumber?: number;
941
+ }
942
+ export interface SitePage {
943
+ /** Full URL */
944
+ url: string;
945
+ /** Path portion of URL */
946
+ path: string;
947
+ /** Page title if available */
948
+ title?: string;
949
+ /** Discovered from source */
950
+ source: "sitemap" | "crawl" | "link";
951
+ /** HTTP status code */
952
+ status?: number;
953
+ /** Links found on this page */
954
+ outboundLinks?: string[];
955
+ /** Interactive elements found */
956
+ interactiveElements?: number;
957
+ /** Forms found */
958
+ formCount?: number;
959
+ }
960
+ export interface CoverageGap {
961
+ /** Page without adequate test coverage */
962
+ page: SitePage;
963
+ /** Why this is flagged as a gap */
964
+ reason: "untested" | "low-coverage" | "no-interactions" | "no-verifications";
965
+ /** Priority level */
966
+ priority: "critical" | "high" | "medium" | "low";
967
+ /** Suggested test steps */
968
+ suggestedTests: string[];
969
+ /** Similar pages that are tested (for reference) */
970
+ similarTestedPages?: string[];
971
+ }
972
+ export interface TestCoverageAnalysis {
973
+ /** Total pages found on site */
974
+ totalPages: number;
975
+ /** Pages with at least one test */
976
+ testedPages: number;
977
+ /** Pages with no tests */
978
+ untestedPages: number;
979
+ /** Overall coverage percentage */
980
+ coveragePercent: number;
981
+ /** Coverage by section/route prefix */
982
+ sectionCoverage: Record<string, {
983
+ total: number;
984
+ tested: number;
985
+ percent: number;
986
+ }>;
987
+ }
988
+ export interface CoverageMapResult {
989
+ /** Base URL of the site */
990
+ baseUrl: string;
991
+ /** Timestamp of analysis */
992
+ timestamp: string;
993
+ /** Duration of analysis */
994
+ duration: number;
995
+ /** Test files analyzed */
996
+ testFiles: string[];
997
+ /** All pages found on site */
998
+ sitePages: SitePage[];
999
+ /** Pages with test coverage */
1000
+ testedPages: TestedPage[];
1001
+ /** Coverage gaps identified */
1002
+ gaps: CoverageGap[];
1003
+ /** Overall analysis */
1004
+ analysis: TestCoverageAnalysis;
1005
+ /** Recommendations */
1006
+ recommendations: string[];
1007
+ }
1008
+ export interface CoverageMapOptions {
1009
+ /** Sitemap URL to use instead of crawling */
1010
+ sitemapUrl?: string;
1011
+ /** Max pages to crawl (default: 100) */
1012
+ maxPages?: number;
1013
+ /** Include only paths matching pattern */
1014
+ includePattern?: string;
1015
+ /** Exclude paths matching pattern */
1016
+ excludePattern?: string;
1017
+ /** Minimum coverage % to not flag as gap (default: 50) */
1018
+ minCoverage?: number;
1019
+ /** Output format */
1020
+ format?: "json" | "html" | "summary";
1021
+ }
813
1022
  //# sourceMappingURL=types.d.ts.map