afterburn-cli 1.0.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/LICENSE +21 -0
- package/README.md +281 -0
- package/dist/ai/gemini-client.d.ts +21 -0
- package/dist/ai/gemini-client.js +105 -0
- package/dist/ai/gemini-client.js.map +1 -0
- package/dist/ai/index.d.ts +1 -0
- package/dist/ai/index.js +3 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/analysis/diagnosis-schema.d.ts +106 -0
- package/dist/analysis/diagnosis-schema.js +54 -0
- package/dist/analysis/diagnosis-schema.js.map +1 -0
- package/dist/analysis/error-analyzer.d.ts +9 -0
- package/dist/analysis/error-analyzer.js +573 -0
- package/dist/analysis/error-analyzer.js.map +1 -0
- package/dist/analysis/index.d.ts +4 -0
- package/dist/analysis/index.js +6 -0
- package/dist/analysis/index.js.map +1 -0
- package/dist/analysis/source-mapper.d.ts +19 -0
- package/dist/analysis/source-mapper.js +329 -0
- package/dist/analysis/source-mapper.js.map +1 -0
- package/dist/analysis/ui-auditor.d.ts +9 -0
- package/dist/analysis/ui-auditor.js +104 -0
- package/dist/analysis/ui-auditor.js.map +1 -0
- package/dist/artifacts/artifact-storage.d.ts +44 -0
- package/dist/artifacts/artifact-storage.js +99 -0
- package/dist/artifacts/artifact-storage.js.map +1 -0
- package/dist/artifacts/index.d.ts +1 -0
- package/dist/artifacts/index.js +3 -0
- package/dist/artifacts/index.js.map +1 -0
- package/dist/browser/browser-manager.d.ts +45 -0
- package/dist/browser/browser-manager.js +88 -0
- package/dist/browser/browser-manager.js.map +1 -0
- package/dist/browser/challenge-detector.d.ts +10 -0
- package/dist/browser/challenge-detector.js +58 -0
- package/dist/browser/challenge-detector.js.map +1 -0
- package/dist/browser/cookie-dismisser.d.ts +18 -0
- package/dist/browser/cookie-dismisser.js +76 -0
- package/dist/browser/cookie-dismisser.js.map +1 -0
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.js +6 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/stealth-browser.d.ts +13 -0
- package/dist/browser/stealth-browser.js +59 -0
- package/dist/browser/stealth-browser.js.map +1 -0
- package/dist/cli/commander-cli.d.ts +2 -0
- package/dist/cli/commander-cli.js +150 -0
- package/dist/cli/commander-cli.js.map +1 -0
- package/dist/cli/doctor.d.ts +34 -0
- package/dist/cli/doctor.js +124 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/first-run.d.ts +6 -0
- package/dist/cli/first-run.js +58 -0
- package/dist/cli/first-run.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +5 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/progress.d.ts +11 -0
- package/dist/cli/progress.js +30 -0
- package/dist/cli/progress.js.map +1 -0
- package/dist/core/engine.d.ts +33 -0
- package/dist/core/engine.js +269 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +4 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/validation.d.ts +52 -0
- package/dist/core/validation.js +228 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/discovery/crawler.d.ts +58 -0
- package/dist/discovery/crawler.js +240 -0
- package/dist/discovery/crawler.js.map +1 -0
- package/dist/discovery/discovery-pipeline.d.ts +22 -0
- package/dist/discovery/discovery-pipeline.js +256 -0
- package/dist/discovery/discovery-pipeline.js.map +1 -0
- package/dist/discovery/element-mapper.d.ts +21 -0
- package/dist/discovery/element-mapper.js +422 -0
- package/dist/discovery/element-mapper.js.map +1 -0
- package/dist/discovery/index.d.ts +8 -0
- package/dist/discovery/index.js +8 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/link-validator.d.ts +15 -0
- package/dist/discovery/link-validator.js +137 -0
- package/dist/discovery/link-validator.js.map +1 -0
- package/dist/discovery/sitemap-builder.d.ts +19 -0
- package/dist/discovery/sitemap-builder.js +166 -0
- package/dist/discovery/sitemap-builder.js.map +1 -0
- package/dist/discovery/spa-detector.d.ts +12 -0
- package/dist/discovery/spa-detector.js +271 -0
- package/dist/discovery/spa-detector.js.map +1 -0
- package/dist/execution/error-detector.d.ts +10 -0
- package/dist/execution/error-detector.js +87 -0
- package/dist/execution/error-detector.js.map +1 -0
- package/dist/execution/evidence-capture.d.ts +8 -0
- package/dist/execution/evidence-capture.js +37 -0
- package/dist/execution/evidence-capture.js.map +1 -0
- package/dist/execution/index.d.ts +5 -0
- package/dist/execution/index.js +7 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/execution/step-handlers.d.ts +48 -0
- package/dist/execution/step-handlers.js +349 -0
- package/dist/execution/step-handlers.js.map +1 -0
- package/dist/execution/test-data.d.ts +50 -0
- package/dist/execution/test-data.js +160 -0
- package/dist/execution/test-data.js.map +1 -0
- package/dist/execution/workflow-executor.d.ts +56 -0
- package/dist/execution/workflow-executor.js +331 -0
- package/dist/execution/workflow-executor.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/entry.d.ts +2 -0
- package/dist/mcp/entry.js +5 -0
- package/dist/mcp/entry.js.map +1 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +4 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.js +19 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +2 -0
- package/dist/mcp/tools.js +162 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/planning/heuristic-planner.d.ts +7 -0
- package/dist/planning/heuristic-planner.js +238 -0
- package/dist/planning/heuristic-planner.js.map +1 -0
- package/dist/planning/index.d.ts +3 -0
- package/dist/planning/index.js +5 -0
- package/dist/planning/index.js.map +1 -0
- package/dist/planning/plan-schema.d.ts +74 -0
- package/dist/planning/plan-schema.js +39 -0
- package/dist/planning/plan-schema.js.map +1 -0
- package/dist/planning/workflow-planner.d.ts +39 -0
- package/dist/planning/workflow-planner.js +211 -0
- package/dist/planning/workflow-planner.js.map +1 -0
- package/dist/reports/health-scorer.d.ts +14 -0
- package/dist/reports/health-scorer.js +88 -0
- package/dist/reports/health-scorer.js.map +1 -0
- package/dist/reports/html-generator.d.ts +10 -0
- package/dist/reports/html-generator.js +155 -0
- package/dist/reports/html-generator.js.map +1 -0
- package/dist/reports/index.d.ts +4 -0
- package/dist/reports/index.js +6 -0
- package/dist/reports/index.js.map +1 -0
- package/dist/reports/markdown-generator.d.ts +10 -0
- package/dist/reports/markdown-generator.js +334 -0
- package/dist/reports/markdown-generator.js.map +1 -0
- package/dist/reports/priority-ranker.d.ts +22 -0
- package/dist/reports/priority-ranker.js +608 -0
- package/dist/reports/priority-ranker.js.map +1 -0
- package/dist/screenshots/dual-format.d.ts +14 -0
- package/dist/screenshots/dual-format.js +59 -0
- package/dist/screenshots/dual-format.js.map +1 -0
- package/dist/screenshots/index.d.ts +2 -0
- package/dist/screenshots/index.js +4 -0
- package/dist/screenshots/index.js.map +1 -0
- package/dist/screenshots/screenshot-manager.d.ts +33 -0
- package/dist/screenshots/screenshot-manager.js +86 -0
- package/dist/screenshots/screenshot-manager.js.map +1 -0
- package/dist/testing/accessibility-auditor.d.ts +23 -0
- package/dist/testing/accessibility-auditor.js +44 -0
- package/dist/testing/accessibility-auditor.js.map +1 -0
- package/dist/testing/index.d.ts +4 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/meta-auditor.d.ts +16 -0
- package/dist/testing/meta-auditor.js +268 -0
- package/dist/testing/meta-auditor.js.map +1 -0
- package/dist/testing/performance-monitor.d.ts +15 -0
- package/dist/testing/performance-monitor.js +64 -0
- package/dist/testing/performance-monitor.js.map +1 -0
- package/dist/types/artifacts.d.ts +58 -0
- package/dist/types/artifacts.js +3 -0
- package/dist/types/artifacts.js.map +1 -0
- package/dist/types/discovery.d.ts +124 -0
- package/dist/types/discovery.js +3 -0
- package/dist/types/discovery.js.map +1 -0
- package/dist/types/execution.d.ts +154 -0
- package/dist/types/execution.js +3 -0
- package/dist/types/execution.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/sanitizer.d.ts +25 -0
- package/dist/utils/sanitizer.js +98 -0
- package/dist/utils/sanitizer.js.map +1 -0
- package/package.json +86 -0
- package/templates/report.hbs +202 -0
- package/templates/styles/report.css +607 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Browser performance metrics capture via Performance API
|
|
2
|
+
/**
|
|
3
|
+
* Capture browser performance metrics from a Playwright page
|
|
4
|
+
*
|
|
5
|
+
* @param page - Playwright page to measure
|
|
6
|
+
* @returns Performance metrics including LCP, DOM load time, and total load time
|
|
7
|
+
*/
|
|
8
|
+
export async function capturePerformanceMetrics(page) {
|
|
9
|
+
try {
|
|
10
|
+
const url = page.url();
|
|
11
|
+
// Wait for load state with timeout
|
|
12
|
+
await page.waitForLoadState('load', { timeout: 10000 });
|
|
13
|
+
// Capture performance metrics via browser Performance API
|
|
14
|
+
const metrics = await page.evaluate(() => {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
let lcpValue = 0;
|
|
17
|
+
// Capture LCP via PerformanceObserver with buffered entries
|
|
18
|
+
const lcpObserver = new PerformanceObserver((list) => {
|
|
19
|
+
const entries = list.getEntries();
|
|
20
|
+
const lastEntry = entries[entries.length - 1];
|
|
21
|
+
if (lastEntry && lastEntry.renderTime) {
|
|
22
|
+
lcpValue = lastEntry.renderTime;
|
|
23
|
+
}
|
|
24
|
+
else if (lastEntry && lastEntry.loadTime) {
|
|
25
|
+
lcpValue = lastEntry.loadTime;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
try {
|
|
29
|
+
lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true });
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
// LCP not supported, will use 0
|
|
33
|
+
}
|
|
34
|
+
// Wait 3 seconds for LCP to settle, then capture navigation timing
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
lcpObserver.disconnect();
|
|
37
|
+
const navigation = performance.getEntriesByType('navigation')[0];
|
|
38
|
+
resolve({
|
|
39
|
+
lcp: lcpValue,
|
|
40
|
+
domContentLoaded: navigation?.domContentLoadedEventEnd || 0,
|
|
41
|
+
totalLoadTime: navigation?.loadEventEnd || 0,
|
|
42
|
+
});
|
|
43
|
+
}, 500);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
url,
|
|
48
|
+
lcp: metrics.lcp,
|
|
49
|
+
domContentLoaded: metrics.domContentLoaded,
|
|
50
|
+
totalLoadTime: metrics.totalLoadTime,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.error('Performance metrics capture failed:', error);
|
|
55
|
+
// Return safe defaults on error
|
|
56
|
+
return {
|
|
57
|
+
url: page.url(),
|
|
58
|
+
lcp: 0,
|
|
59
|
+
domContentLoaded: 0,
|
|
60
|
+
totalLoadTime: 0,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=performance-monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance-monitor.js","sourceRoot":"","sources":["../../src/testing/performance-monitor.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAY1D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,IAAU;IACxD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,mCAAmC;QACnC,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAExD,0DAA0D;QAC1D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE;YACvC,OAAO,IAAI,OAAO,CAIf,CAAC,OAAO,EAAE,EAAE;gBACb,IAAI,QAAQ,GAAG,CAAC,CAAC;gBAEjB,4DAA4D;gBAC5D,MAAM,WAAW,GAAG,IAAI,mBAAmB,CAAC,CAAC,IAAI,EAAE,EAAE;oBACnD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;oBAClC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAQ,CAAC;oBACrD,IAAI,SAAS,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;wBACtC,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC;oBAClC,CAAC;yBAAM,IAAI,SAAS,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;wBAC3C,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC;oBAChC,CAAC;gBACH,CAAC,CAAC,CAAC;gBAEH,IAAI,CAAC;oBACH,WAAW,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,0BAA0B,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC5E,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,gCAAgC;gBAClC,CAAC;gBAED,mEAAmE;gBACnE,UAAU,CAAC,GAAG,EAAE;oBACd,WAAW,CAAC,UAAU,EAAE,CAAC;oBAEzB,MAAM,UAAU,GAAG,WAAW,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAgC,CAAC;oBAEhG,OAAO,CAAC;wBACN,GAAG,EAAE,QAAQ;wBACb,gBAAgB,EAAE,UAAU,EAAE,wBAAwB,IAAI,CAAC;wBAC3D,aAAa,EAAE,UAAU,EAAE,YAAY,IAAI,CAAC;qBAC7C,CAAC,CAAC;gBACL,CAAC,EAAE,GAAG,CAAC,CAAC;YACV,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO;YACL,GAAG;YACH,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;YAC1C,aAAa,EAAE,OAAO,CAAC,aAAa;SACrC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;QAE5D,gCAAgC;QAChC,OAAO;YACL,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE;YACf,GAAG,EAAE,CAAC;YACN,gBAAgB,EAAE,CAAC;YACnB,aAAa,EAAE,CAAC;SACjB,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base interface for all artifacts produced by pipeline stages
|
|
3
|
+
*/
|
|
4
|
+
export interface ArtifactMetadata {
|
|
5
|
+
version: string;
|
|
6
|
+
stage: string;
|
|
7
|
+
timestamp: string;
|
|
8
|
+
sessionId: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Reference to a captured screenshot with dual-format storage
|
|
12
|
+
*/
|
|
13
|
+
export interface ScreenshotRef {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
pngPath: string;
|
|
17
|
+
webpPath: string;
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
sizes: {
|
|
21
|
+
png: number;
|
|
22
|
+
webp: number;
|
|
23
|
+
reduction: string;
|
|
24
|
+
};
|
|
25
|
+
capturedAt: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Cookie consent platform definition
|
|
29
|
+
*/
|
|
30
|
+
export interface CookieBannerSelector {
|
|
31
|
+
name: string;
|
|
32
|
+
acceptButton: string;
|
|
33
|
+
rejectButton?: string;
|
|
34
|
+
modal?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Configuration for a single Afterburn run
|
|
38
|
+
*/
|
|
39
|
+
export interface SessionConfig {
|
|
40
|
+
sessionId: string;
|
|
41
|
+
targetUrl: string;
|
|
42
|
+
startedAt: string;
|
|
43
|
+
artifactDir: string;
|
|
44
|
+
screenshotDir: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Browser launch configuration
|
|
48
|
+
*/
|
|
49
|
+
export interface BrowserConfig {
|
|
50
|
+
headless: boolean;
|
|
51
|
+
userAgent: string;
|
|
52
|
+
viewport: {
|
|
53
|
+
width: number;
|
|
54
|
+
height: number;
|
|
55
|
+
};
|
|
56
|
+
locale: string;
|
|
57
|
+
timezoneId: string;
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../src/types/artifacts.ts"],"names":[],"mappings":"AAAA,gEAAgE"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { ArtifactMetadata, ScreenshotRef } from './artifacts.js';
|
|
2
|
+
/**
|
|
3
|
+
* Individual form input/textarea/select field
|
|
4
|
+
*/
|
|
5
|
+
export interface FormField {
|
|
6
|
+
type: string;
|
|
7
|
+
name: string;
|
|
8
|
+
label: string;
|
|
9
|
+
required: boolean;
|
|
10
|
+
placeholder: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Complete form with all its fields
|
|
14
|
+
*/
|
|
15
|
+
export interface FormInfo {
|
|
16
|
+
action: string;
|
|
17
|
+
method: string;
|
|
18
|
+
selector: string;
|
|
19
|
+
fields: FormField[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Any clickable/interactive element on a page
|
|
23
|
+
*/
|
|
24
|
+
export interface InteractiveElement {
|
|
25
|
+
type: 'button' | 'link' | 'input' | 'select' | 'menu' | 'tab' | 'modal-trigger';
|
|
26
|
+
selector: string;
|
|
27
|
+
text: string;
|
|
28
|
+
visible: boolean;
|
|
29
|
+
attributes: Record<string, string>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A link found on a page
|
|
33
|
+
*/
|
|
34
|
+
export interface LinkInfo {
|
|
35
|
+
href: string;
|
|
36
|
+
text: string;
|
|
37
|
+
isInternal: boolean;
|
|
38
|
+
statusCode?: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Everything discovered about a single page
|
|
42
|
+
*/
|
|
43
|
+
export interface PageData {
|
|
44
|
+
url: string;
|
|
45
|
+
title: string;
|
|
46
|
+
forms: FormInfo[];
|
|
47
|
+
buttons: InteractiveElement[];
|
|
48
|
+
links: LinkInfo[];
|
|
49
|
+
menus: InteractiveElement[];
|
|
50
|
+
otherInteractive: InteractiveElement[];
|
|
51
|
+
screenshotRef?: ScreenshotRef;
|
|
52
|
+
spaFramework?: SPAFramework;
|
|
53
|
+
crawledAt: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Detected SPA framework info
|
|
57
|
+
*/
|
|
58
|
+
export interface SPAFramework {
|
|
59
|
+
framework: 'react' | 'vue' | 'angular' | 'next' | 'svelte' | 'nuxt' | 'none';
|
|
60
|
+
version?: string;
|
|
61
|
+
router?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Hierarchical tree node for sitemap
|
|
65
|
+
*/
|
|
66
|
+
export interface SitemapNode {
|
|
67
|
+
url: string;
|
|
68
|
+
title: string;
|
|
69
|
+
path: string;
|
|
70
|
+
children: SitemapNode[];
|
|
71
|
+
pageData: PageData;
|
|
72
|
+
depth: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* A link that returned non-2xx status
|
|
76
|
+
*/
|
|
77
|
+
export interface BrokenLink {
|
|
78
|
+
url: string;
|
|
79
|
+
sourceUrl: string;
|
|
80
|
+
statusCode: number;
|
|
81
|
+
statusText: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Single step in a workflow plan
|
|
85
|
+
*/
|
|
86
|
+
export interface WorkflowStep {
|
|
87
|
+
action: 'navigate' | 'click' | 'fill' | 'select' | 'wait' | 'expect';
|
|
88
|
+
selector: string;
|
|
89
|
+
value?: string;
|
|
90
|
+
expectedResult: string;
|
|
91
|
+
confidence: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* AI-generated test plan
|
|
95
|
+
*/
|
|
96
|
+
export interface WorkflowPlan {
|
|
97
|
+
workflowName: string;
|
|
98
|
+
description: string;
|
|
99
|
+
steps: WorkflowStep[];
|
|
100
|
+
priority: 'critical' | 'important' | 'nice-to-have';
|
|
101
|
+
estimatedDuration: number;
|
|
102
|
+
source: 'auto-discovered' | 'user-hint';
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Output of the crawler
|
|
106
|
+
*/
|
|
107
|
+
export interface CrawlResult {
|
|
108
|
+
pages: PageData[];
|
|
109
|
+
brokenLinks: BrokenLink[];
|
|
110
|
+
totalPagesDiscovered: number;
|
|
111
|
+
totalLinksChecked: number;
|
|
112
|
+
crawlDuration: number;
|
|
113
|
+
spaDetected: SPAFramework;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Complete Phase 2 output artifact (extends ArtifactMetadata)
|
|
117
|
+
*/
|
|
118
|
+
export interface DiscoveryArtifact extends ArtifactMetadata {
|
|
119
|
+
targetUrl: string;
|
|
120
|
+
sitemap: SitemapNode;
|
|
121
|
+
crawlResult: CrawlResult;
|
|
122
|
+
workflowPlans: WorkflowPlan[];
|
|
123
|
+
userHints: string[];
|
|
124
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/types/discovery.ts"],"names":[],"mappings":"AAAA,8DAA8D"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { ScreenshotRef } from './artifacts.js';
|
|
2
|
+
/**
|
|
3
|
+
* Collector for errors detected during workflow execution
|
|
4
|
+
*/
|
|
5
|
+
export interface ErrorCollector {
|
|
6
|
+
consoleErrors: Array<{
|
|
7
|
+
message: string;
|
|
8
|
+
url: string;
|
|
9
|
+
timestamp: string;
|
|
10
|
+
}>;
|
|
11
|
+
networkFailures: Array<{
|
|
12
|
+
url: string;
|
|
13
|
+
status: number;
|
|
14
|
+
method: string;
|
|
15
|
+
resourceType: string;
|
|
16
|
+
}>;
|
|
17
|
+
brokenImages: Array<{
|
|
18
|
+
url: string;
|
|
19
|
+
selector: string;
|
|
20
|
+
status: number;
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Evidence captured when a workflow step fails
|
|
25
|
+
*/
|
|
26
|
+
export interface ErrorEvidence {
|
|
27
|
+
screenshotRef?: ScreenshotRef;
|
|
28
|
+
consoleErrors: string[];
|
|
29
|
+
networkFailures: Array<{
|
|
30
|
+
url: string;
|
|
31
|
+
status: number;
|
|
32
|
+
}>;
|
|
33
|
+
pageUrl: string;
|
|
34
|
+
timestamp: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Result of a single workflow step execution
|
|
38
|
+
*/
|
|
39
|
+
export interface StepResult {
|
|
40
|
+
stepIndex: number;
|
|
41
|
+
action: string;
|
|
42
|
+
selector: string;
|
|
43
|
+
status: 'passed' | 'failed' | 'skipped';
|
|
44
|
+
duration: number;
|
|
45
|
+
error?: string;
|
|
46
|
+
evidence?: ErrorEvidence;
|
|
47
|
+
skippedFields?: Array<{
|
|
48
|
+
selector: string;
|
|
49
|
+
reason: string;
|
|
50
|
+
}>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Result of dead button detection test
|
|
54
|
+
*/
|
|
55
|
+
export interface DeadButtonResult {
|
|
56
|
+
isDead: boolean;
|
|
57
|
+
selector: string;
|
|
58
|
+
reason?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Result of broken form detection test
|
|
62
|
+
*/
|
|
63
|
+
export interface BrokenFormResult {
|
|
64
|
+
isBroken: boolean;
|
|
65
|
+
formSelector: string;
|
|
66
|
+
reason?: string;
|
|
67
|
+
filledFields: number;
|
|
68
|
+
skippedFields: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Performance metrics captured from browser APIs
|
|
72
|
+
*/
|
|
73
|
+
export interface PerformanceMetrics {
|
|
74
|
+
lcp: number;
|
|
75
|
+
domContentLoaded: number;
|
|
76
|
+
totalLoadTime: number;
|
|
77
|
+
url: string;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Individual accessibility violation found by axe-core
|
|
81
|
+
*/
|
|
82
|
+
export interface AccessibilityViolation {
|
|
83
|
+
id: string;
|
|
84
|
+
impact: 'critical' | 'serious' | 'moderate' | 'minor';
|
|
85
|
+
description: string;
|
|
86
|
+
nodes: number;
|
|
87
|
+
helpUrl: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Accessibility audit report for a single page
|
|
91
|
+
*/
|
|
92
|
+
export interface AccessibilityReport {
|
|
93
|
+
url: string;
|
|
94
|
+
violationCount: number;
|
|
95
|
+
violations: AccessibilityViolation[];
|
|
96
|
+
passes: number;
|
|
97
|
+
incomplete: number;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Result of executing a complete workflow
|
|
101
|
+
*/
|
|
102
|
+
export interface WorkflowExecutionResult {
|
|
103
|
+
workflowName: string;
|
|
104
|
+
description: string;
|
|
105
|
+
totalSteps: number;
|
|
106
|
+
passedSteps: number;
|
|
107
|
+
failedSteps: number;
|
|
108
|
+
skippedSteps: number;
|
|
109
|
+
stepResults: StepResult[];
|
|
110
|
+
errors: ErrorCollector;
|
|
111
|
+
overallStatus: 'passed' | 'failed';
|
|
112
|
+
duration: number;
|
|
113
|
+
pageScreenshotRef?: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* A link discovered during crawl that returned non-2xx status
|
|
117
|
+
*/
|
|
118
|
+
export interface BrokenLinkIssue {
|
|
119
|
+
url: string;
|
|
120
|
+
sourceUrl: string;
|
|
121
|
+
statusCode: number;
|
|
122
|
+
statusText: string;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Complete execution artifact containing all test results
|
|
126
|
+
*/
|
|
127
|
+
/**
|
|
128
|
+
* Individual meta/SEO issue found by heuristic auditor
|
|
129
|
+
*/
|
|
130
|
+
export interface MetaIssueResult {
|
|
131
|
+
id: string;
|
|
132
|
+
severity: 'high' | 'medium' | 'low';
|
|
133
|
+
description: string;
|
|
134
|
+
suggestion: string;
|
|
135
|
+
}
|
|
136
|
+
export interface ExecutionArtifact {
|
|
137
|
+
version: string;
|
|
138
|
+
stage: string;
|
|
139
|
+
timestamp: string;
|
|
140
|
+
sessionId: string;
|
|
141
|
+
targetUrl: string;
|
|
142
|
+
workflowResults: WorkflowExecutionResult[];
|
|
143
|
+
pageAudits: Array<{
|
|
144
|
+
url: string;
|
|
145
|
+
accessibility?: AccessibilityReport;
|
|
146
|
+
performance?: PerformanceMetrics;
|
|
147
|
+
metaIssues?: MetaIssueResult[];
|
|
148
|
+
}>;
|
|
149
|
+
deadButtons: DeadButtonResult[];
|
|
150
|
+
brokenForms: BrokenFormResult[];
|
|
151
|
+
brokenLinks: BrokenLinkIssue[];
|
|
152
|
+
totalIssues: number;
|
|
153
|
+
exitCode: number;
|
|
154
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution.js","sourceRoot":"","sources":["../../src/types/execution.ts"],"names":[],"mappings":"AAAA,gFAAgF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redact clearly sensitive patterns from text while preserving useful error context.
|
|
3
|
+
* Conservative approach: only redact things that are obviously secrets.
|
|
4
|
+
*/
|
|
5
|
+
export declare function redactSensitiveData(text: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Redact sensitive query parameters from URLs before they reach reports or LLM prompts.
|
|
8
|
+
* Falls back to general text redaction if the URL cannot be parsed.
|
|
9
|
+
*/
|
|
10
|
+
export declare function redactSensitiveUrl(url: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Sanitize a string for safe inclusion in YAML values.
|
|
13
|
+
* Wraps in double quotes and escapes if value contains YAML special characters.
|
|
14
|
+
*/
|
|
15
|
+
export declare function sanitizeForYaml(value: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Sanitize a string for safe inclusion in Markdown tables.
|
|
18
|
+
* Escapes pipe characters and removes newlines.
|
|
19
|
+
*/
|
|
20
|
+
export declare function sanitizeForMarkdown(text: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Sanitize a string for safe inclusion in markdown inline content.
|
|
23
|
+
* Escapes pipes/backticks and replaces newlines.
|
|
24
|
+
*/
|
|
25
|
+
export declare function sanitizeForMarkdownInline(text: string): string;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// Redacts sensitive data (API keys, tokens, passwords) from text before it reaches LLM prompts or PR comments
|
|
2
|
+
/**
|
|
3
|
+
* Redact clearly sensitive patterns from text while preserving useful error context.
|
|
4
|
+
* Conservative approach: only redact things that are obviously secrets.
|
|
5
|
+
*/
|
|
6
|
+
export function redactSensitiveData(text) {
|
|
7
|
+
if (!text)
|
|
8
|
+
return text;
|
|
9
|
+
let redacted = text;
|
|
10
|
+
// API key prefixes (OpenAI, GitHub, AWS, Anthropic, Stripe, etc.)
|
|
11
|
+
redacted = redacted.replace(/\b(sk-[a-zA-Z0-9]{20,})/g, '[REDACTED_API_KEY]');
|
|
12
|
+
redacted = redacted.replace(/\b(ghp_[a-zA-Z0-9]{36,})/g, '[REDACTED_GITHUB_TOKEN]');
|
|
13
|
+
redacted = redacted.replace(/\b(ghu_[a-zA-Z0-9]{36,})/g, '[REDACTED_GITHUB_TOKEN]');
|
|
14
|
+
redacted = redacted.replace(/\b(gho_[a-zA-Z0-9]{36,})/g, '[REDACTED_GITHUB_TOKEN]');
|
|
15
|
+
redacted = redacted.replace(/\b(ghs_[a-zA-Z0-9]{36,})/g, '[REDACTED_GITHUB_TOKEN]');
|
|
16
|
+
redacted = redacted.replace(/\b(github_pat_[a-zA-Z0-9_]{22,})/g, '[REDACTED_GITHUB_TOKEN]');
|
|
17
|
+
redacted = redacted.replace(/\b(AKIA[0-9A-Z]{16})/g, '[REDACTED_AWS_KEY]');
|
|
18
|
+
redacted = redacted.replace(/\b(sk-ant-[a-zA-Z0-9-]{20,})/g, '[REDACTED_API_KEY]');
|
|
19
|
+
redacted = redacted.replace(/\b(sk_live_[a-zA-Z0-9]{20,})/g, '[REDACTED_STRIPE_KEY]');
|
|
20
|
+
redacted = redacted.replace(/\b(sk_test_[a-zA-Z0-9]{20,})/g, '[REDACTED_STRIPE_KEY]');
|
|
21
|
+
redacted = redacted.replace(/\b(rk_live_[a-zA-Z0-9]{20,})/g, '[REDACTED_STRIPE_KEY]');
|
|
22
|
+
redacted = redacted.replace(/\b(rk_test_[a-zA-Z0-9]{20,})/g, '[REDACTED_STRIPE_KEY]');
|
|
23
|
+
// Bearer tokens in headers
|
|
24
|
+
redacted = redacted.replace(/(Bearer\s+)[a-zA-Z0-9._\-]{20,}/gi, '$1[REDACTED_TOKEN]');
|
|
25
|
+
// Authorization headers with token values
|
|
26
|
+
redacted = redacted.replace(/(Authorization:\s*)[^\s\n]{20,}/gi, '$1[REDACTED_TOKEN]');
|
|
27
|
+
// password=... or passwd=... or secret=... in query strings or config
|
|
28
|
+
redacted = redacted.replace(/((?:password|passwd|secret|token|apikey|api_key|access_token|auth_token)\s*[=:]\s*)("[^"]*"|'[^']*'|\S{8,})/gi, '$1[REDACTED]');
|
|
29
|
+
// Long hex strings (40+ chars, like SHA tokens or secret keys)
|
|
30
|
+
redacted = redacted.replace(/\b[0-9a-f]{40,}\b/gi, '[REDACTED_HEX_TOKEN]');
|
|
31
|
+
// Long base64-looking strings (32+ chars of alphanumeric with +/=)
|
|
32
|
+
// Only match standalone tokens, not error message prose
|
|
33
|
+
redacted = redacted.replace(/\b[A-Za-z0-9+/]{32,}={0,2}\b/g, (match) => {
|
|
34
|
+
// Only redact if it looks like a real token (has mixed case + digits, not just a word)
|
|
35
|
+
const hasUpper = /[A-Z]/.test(match);
|
|
36
|
+
const hasLower = /[a-z]/.test(match);
|
|
37
|
+
const hasDigit = /[0-9]/.test(match);
|
|
38
|
+
if (hasUpper && hasLower && hasDigit) {
|
|
39
|
+
return '[REDACTED_BASE64_TOKEN]';
|
|
40
|
+
}
|
|
41
|
+
return match;
|
|
42
|
+
});
|
|
43
|
+
return redacted;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Redact sensitive query parameters from URLs before they reach reports or LLM prompts.
|
|
47
|
+
* Falls back to general text redaction if the URL cannot be parsed.
|
|
48
|
+
*/
|
|
49
|
+
export function redactSensitiveUrl(url) {
|
|
50
|
+
if (!url)
|
|
51
|
+
return url;
|
|
52
|
+
try {
|
|
53
|
+
const parsed = new URL(url);
|
|
54
|
+
const sensitiveParams = ['token', 'key', 'apikey', 'api_key', 'secret', 'password', 'passwd', 'access_token', 'auth_token', 'session', 'jwt'];
|
|
55
|
+
for (const param of sensitiveParams) {
|
|
56
|
+
if (parsed.searchParams.has(param)) {
|
|
57
|
+
parsed.searchParams.set(param, '[REDACTED]');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return parsed.toString();
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return redactSensitiveData(url);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Sanitize a string for safe inclusion in YAML values.
|
|
68
|
+
* Wraps in double quotes and escapes if value contains YAML special characters.
|
|
69
|
+
*/
|
|
70
|
+
export function sanitizeForYaml(value) {
|
|
71
|
+
if (!value)
|
|
72
|
+
return '""';
|
|
73
|
+
// If value contains YAML special chars, wrap in double quotes and escape internal quotes
|
|
74
|
+
if (/[:{}\[\]#&*!|>'"% @`\n]/.test(value)) {
|
|
75
|
+
return '"' + value.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
|
|
76
|
+
}
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Sanitize a string for safe inclusion in Markdown tables.
|
|
81
|
+
* Escapes pipe characters and removes newlines.
|
|
82
|
+
*/
|
|
83
|
+
export function sanitizeForMarkdown(text) {
|
|
84
|
+
return sanitizeForMarkdownInline(text);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Sanitize a string for safe inclusion in markdown inline content.
|
|
88
|
+
* Escapes pipes/backticks and replaces newlines.
|
|
89
|
+
*/
|
|
90
|
+
export function sanitizeForMarkdownInline(text) {
|
|
91
|
+
if (!text)
|
|
92
|
+
return '';
|
|
93
|
+
return text
|
|
94
|
+
.replace(/\|/g, '\\|')
|
|
95
|
+
.replace(/`/g, '\\`')
|
|
96
|
+
.replace(/\r?\n/g, ' ');
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=sanitizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../../src/utils/sanitizer.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "afterburn-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Automated testing for vibe-coded websites. One command finds broken forms, dead buttons, JS crashes, and more.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=18"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/gods-strongest-vibecoder/afterburn#readme",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"build:action": "tsc -p action/tsconfig.json",
|
|
14
|
+
"bundle:action": "ncc build action/index.js -o action/dist --license licenses.txt",
|
|
15
|
+
"build:release": "npm run build && npm run build:action && npm run bundle:action",
|
|
16
|
+
"dev": "tsx src/index.ts",
|
|
17
|
+
"start": "node dist/index.js",
|
|
18
|
+
"test": "npm run test:unit",
|
|
19
|
+
"test:unit": "vitest run --config vitest.config.unit.ts",
|
|
20
|
+
"pretest:e2e": "npm run build",
|
|
21
|
+
"test:e2e": "vitest run --config vitest.config.e2e.ts",
|
|
22
|
+
"test:smoke:external": "vitest run --config vitest.config.e2e.ts tests/e2e/external-smoke.test.ts",
|
|
23
|
+
"test:coverage": "vitest run --config vitest.config.unit.ts --coverage",
|
|
24
|
+
"test:watch": "vitest --config vitest.config.unit.ts"
|
|
25
|
+
},
|
|
26
|
+
"bin": {
|
|
27
|
+
"afterburn": "dist/index.js",
|
|
28
|
+
"afterburn-cli": "dist/index.js",
|
|
29
|
+
"afterburn-mcp": "dist/mcp/entry.js"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"templates"
|
|
34
|
+
],
|
|
35
|
+
"keywords": [
|
|
36
|
+
"testing",
|
|
37
|
+
"automation",
|
|
38
|
+
"playwright",
|
|
39
|
+
"website-testing",
|
|
40
|
+
"accessibility",
|
|
41
|
+
"vibe-coding",
|
|
42
|
+
"cli-tool",
|
|
43
|
+
"developer-tools",
|
|
44
|
+
"bug-detection",
|
|
45
|
+
"qa-automation",
|
|
46
|
+
"mcp",
|
|
47
|
+
"ai-tools",
|
|
48
|
+
"web-development"
|
|
49
|
+
],
|
|
50
|
+
"author": "Afterburn",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "https://github.com/gods-strongest-vibecoder/afterburn"
|
|
54
|
+
},
|
|
55
|
+
"license": "MIT",
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@axe-core/playwright": "^4.11.1",
|
|
58
|
+
"@google/generative-ai": "^0.24.1",
|
|
59
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
60
|
+
"chalk": "^5.6.2",
|
|
61
|
+
"commander": "^14.0.3",
|
|
62
|
+
"fs-extra": "^11.3.3",
|
|
63
|
+
"handlebars": "^4.7.8",
|
|
64
|
+
"marked": "^17.0.1",
|
|
65
|
+
"ora": "^9.3.0",
|
|
66
|
+
"playwright": "^1.58.2",
|
|
67
|
+
"playwright-extra": "4.3.6",
|
|
68
|
+
"puppeteer-extra-plugin-stealth": "2.11.2",
|
|
69
|
+
"sharp": "^0.34.5",
|
|
70
|
+
"ts-morph": "^27.0.2",
|
|
71
|
+
"zod": "^4.3.6",
|
|
72
|
+
"zod-to-json-schema": "^3.25.1"
|
|
73
|
+
},
|
|
74
|
+
"devDependencies": {
|
|
75
|
+
"@actions/artifact": "^6.1.0",
|
|
76
|
+
"@actions/core": "^3.0.0",
|
|
77
|
+
"@actions/github": "^9.0.0",
|
|
78
|
+
"@types/fs-extra": "^11.0.4",
|
|
79
|
+
"@types/node": "^25.2.1",
|
|
80
|
+
"@vercel/ncc": "^0.38.4",
|
|
81
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
82
|
+
"tsx": "^4.21.0",
|
|
83
|
+
"typescript": "^5.9.3",
|
|
84
|
+
"vitest": "^4.0.18"
|
|
85
|
+
}
|
|
86
|
+
}
|