cbrowser 7.2.0 → 7.4.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/analysis/bug-hunter.d.ts +32 -0
- package/dist/analysis/bug-hunter.d.ts.map +1 -0
- package/dist/analysis/bug-hunter.js +106 -0
- package/dist/analysis/bug-hunter.js.map +1 -0
- package/dist/analysis/chaos-testing.d.ts +41 -0
- package/dist/analysis/chaos-testing.d.ts.map +1 -0
- package/dist/analysis/chaos-testing.js +87 -0
- package/dist/analysis/chaos-testing.js.map +1 -0
- package/dist/analysis/index.d.ts +10 -0
- package/dist/analysis/index.d.ts.map +1 -0
- package/dist/analysis/index.js +26 -0
- package/dist/analysis/index.js.map +1 -0
- package/dist/analysis/natural-language.d.ts +43 -0
- package/dist/analysis/natural-language.d.ts.map +1 -0
- package/dist/analysis/natural-language.js +205 -0
- package/dist/analysis/natural-language.js.map +1 -0
- package/dist/analysis/persona-comparison.d.ts +31 -0
- package/dist/analysis/persona-comparison.d.ts.map +1 -0
- package/dist/analysis/persona-comparison.js +217 -0
- package/dist/analysis/persona-comparison.js.map +1 -0
- package/dist/browser.d.ts +1 -395
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +0 -4388
- package/dist/browser.js.map +1 -1
- package/dist/cli.js +198 -55
- package/dist/cli.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +2 -1
- package/dist/daemon.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/performance/index.d.ts +7 -0
- package/dist/performance/index.d.ts.map +1 -0
- package/dist/performance/index.js +23 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/performance/metrics.d.ts +49 -0
- package/dist/performance/metrics.d.ts.map +1 -0
- package/dist/performance/metrics.js +386 -0
- package/dist/performance/metrics.js.map +1 -0
- package/dist/testing/coverage.d.ts +39 -0
- package/dist/testing/coverage.d.ts.map +1 -0
- package/dist/testing/coverage.js +713 -0
- package/dist/testing/coverage.js.map +1 -0
- package/dist/testing/flaky-detection.d.ts +28 -0
- package/dist/testing/flaky-detection.d.ts.map +1 -0
- package/dist/testing/flaky-detection.js +332 -0
- package/dist/testing/flaky-detection.js.map +1 -0
- package/dist/testing/index.d.ts +10 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +26 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/nl-test-suite.d.ts +70 -0
- package/dist/testing/nl-test-suite.d.ts.map +1 -0
- package/dist/testing/nl-test-suite.js +427 -0
- package/dist/testing/nl-test-suite.js.map +1 -0
- package/dist/testing/test-repair.d.ts +36 -0
- package/dist/testing/test-repair.d.ts.map +1 -0
- package/dist/testing/test-repair.js +528 -0
- package/dist/testing/test-repair.js.map +1 -0
- package/dist/types.d.ts +125 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/visual/ab-comparison.d.ts +23 -0
- package/dist/visual/ab-comparison.d.ts.map +1 -0
- package/dist/visual/ab-comparison.js +366 -0
- package/dist/visual/ab-comparison.js.map +1 -0
- package/dist/visual/cross-browser.d.ts +41 -0
- package/dist/visual/cross-browser.d.ts.map +1 -0
- package/dist/visual/cross-browser.js +442 -0
- package/dist/visual/cross-browser.js.map +1 -0
- package/dist/visual/index.d.ts +10 -0
- package/dist/visual/index.d.ts.map +1 -0
- package/dist/visual/index.js +26 -0
- package/dist/visual/index.js.map +1 -0
- package/dist/visual/regression.d.ts +55 -0
- package/dist/visual/regression.d.ts.map +1 -0
- package/dist/visual/regression.js +616 -0
- package/dist/visual/regression.js.map +1 -0
- package/dist/visual/responsive.d.ts +27 -0
- package/dist/visual/responsive.d.ts.map +1 -0
- package/dist/visual/responsive.js +450 -0
- package/dist/visual/responsive.js.map +1 -0
- package/package.json +32 -3
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cross-Browser Visual Testing (v7.1.0)
|
|
4
|
+
*
|
|
5
|
+
* Test how pages render across different browser engines.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.runCrossBrowserTest = runCrossBrowserTest;
|
|
9
|
+
exports.runCrossBrowserSuite = runCrossBrowserSuite;
|
|
10
|
+
exports.formatCrossBrowserReport = formatCrossBrowserReport;
|
|
11
|
+
exports.generateCrossBrowserHtmlReport = generateCrossBrowserHtmlReport;
|
|
12
|
+
exports.crossBrowserDiff = crossBrowserDiff;
|
|
13
|
+
const fs_1 = require("fs");
|
|
14
|
+
const path_1 = require("path");
|
|
15
|
+
const browser_js_1 = require("../browser.js");
|
|
16
|
+
const regression_js_1 = require("./regression.js");
|
|
17
|
+
/**
|
|
18
|
+
* Get the path for cross-browser screenshots
|
|
19
|
+
*/
|
|
20
|
+
function getCrossBrowserScreenshotsPath() {
|
|
21
|
+
const baseDir = process.env.CBROWSER_DATA_DIR || (0, path_1.join)(process.cwd(), ".cbrowser");
|
|
22
|
+
const dir = (0, path_1.join)(baseDir, "cross-browser");
|
|
23
|
+
if (!(0, fs_1.existsSync)(dir)) {
|
|
24
|
+
(0, fs_1.mkdirSync)(dir, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
return dir;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Capture screenshot with a specific browser
|
|
30
|
+
*/
|
|
31
|
+
async function captureWithBrowser(url, browserType, options = {}) {
|
|
32
|
+
const startTime = Date.now();
|
|
33
|
+
const browser = new browser_js_1.CBrowser({
|
|
34
|
+
browser: browserType,
|
|
35
|
+
viewportWidth: options.viewport?.width || 1920,
|
|
36
|
+
viewportHeight: options.viewport?.height || 1080,
|
|
37
|
+
});
|
|
38
|
+
try {
|
|
39
|
+
await browser.launch();
|
|
40
|
+
await browser.navigate(url);
|
|
41
|
+
// Wait if specified
|
|
42
|
+
if (options.waitForSelector) {
|
|
43
|
+
const page = await browser.getPage();
|
|
44
|
+
await page.waitForSelector(options.waitForSelector, { timeout: 10000 }).catch(() => { });
|
|
45
|
+
}
|
|
46
|
+
if (options.waitBeforeCapture) {
|
|
47
|
+
await new Promise(resolve => setTimeout(resolve, options.waitBeforeCapture));
|
|
48
|
+
}
|
|
49
|
+
// Take screenshot
|
|
50
|
+
const screenshotsPath = getCrossBrowserScreenshotsPath();
|
|
51
|
+
const filename = `${browserType}-${Date.now()}.png`;
|
|
52
|
+
const screenshotPath = (0, path_1.join)(screenshotsPath, filename);
|
|
53
|
+
const page = await browser.getPage();
|
|
54
|
+
await page.screenshot({ path: screenshotPath, fullPage: false });
|
|
55
|
+
// Get user agent
|
|
56
|
+
const userAgent = await page.evaluate(() => navigator.userAgent);
|
|
57
|
+
const viewport = page.viewportSize() || { width: 1920, height: 1080 };
|
|
58
|
+
return {
|
|
59
|
+
browser: browserType,
|
|
60
|
+
screenshotPath,
|
|
61
|
+
viewport,
|
|
62
|
+
userAgent,
|
|
63
|
+
timestamp: new Date().toISOString(),
|
|
64
|
+
captureTime: Date.now() - startTime,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
await browser.close();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Run cross-browser visual test for a single URL
|
|
73
|
+
*/
|
|
74
|
+
async function runCrossBrowserTest(url, options = {}) {
|
|
75
|
+
const startTime = Date.now();
|
|
76
|
+
const browsers = options.browsers || ["chromium", "firefox", "webkit"];
|
|
77
|
+
console.log(`\n🌐 Cross-Browser Visual Test`);
|
|
78
|
+
console.log(` URL: ${url}`);
|
|
79
|
+
console.log(` Browsers: ${browsers.join(", ")}\n`);
|
|
80
|
+
// Capture screenshots from each browser
|
|
81
|
+
const screenshots = [];
|
|
82
|
+
for (const browserType of browsers) {
|
|
83
|
+
console.log(` 📸 Capturing ${browserType}...`);
|
|
84
|
+
try {
|
|
85
|
+
const screenshot = await captureWithBrowser(url, browserType, options);
|
|
86
|
+
screenshots.push(screenshot);
|
|
87
|
+
console.log(` ✅ Captured in ${screenshot.captureTime}ms`);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.log(` ❌ Failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (screenshots.length < 2) {
|
|
94
|
+
return {
|
|
95
|
+
url,
|
|
96
|
+
screenshots,
|
|
97
|
+
comparisons: [],
|
|
98
|
+
overallStatus: "major_differences",
|
|
99
|
+
summary: "Could not capture enough screenshots for comparison",
|
|
100
|
+
problematicBrowsers: [],
|
|
101
|
+
duration: Date.now() - startTime,
|
|
102
|
+
timestamp: new Date().toISOString(),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// Compare all pairs of browsers
|
|
106
|
+
const comparisons = [];
|
|
107
|
+
let hasMinorDifferences = false;
|
|
108
|
+
let hasMajorDifferences = false;
|
|
109
|
+
const problematicBrowsers = new Set();
|
|
110
|
+
console.log(`\n 🔍 Comparing browsers...`);
|
|
111
|
+
for (let i = 0; i < screenshots.length; i++) {
|
|
112
|
+
for (let j = i + 1; j < screenshots.length; j++) {
|
|
113
|
+
const a = screenshots[i];
|
|
114
|
+
const b = screenshots[j];
|
|
115
|
+
console.log(` ${a.browser} vs ${b.browser}...`);
|
|
116
|
+
// Use the existing AI visual analysis
|
|
117
|
+
const analysis = await (0, regression_js_1.analyzeVisualDifferences)(a.screenshotPath, b.screenshotPath, { sensitivity: options.sensitivity || "medium" });
|
|
118
|
+
comparisons.push({
|
|
119
|
+
browserA: a.browser,
|
|
120
|
+
browserB: b.browser,
|
|
121
|
+
analysis,
|
|
122
|
+
screenshots: {
|
|
123
|
+
a: a.screenshotPath,
|
|
124
|
+
b: b.screenshotPath,
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
if (analysis.overallStatus === "fail") {
|
|
128
|
+
hasMajorDifferences = true;
|
|
129
|
+
problematicBrowsers.add(a.browser);
|
|
130
|
+
problematicBrowsers.add(b.browser);
|
|
131
|
+
console.log(` ❌ Major differences (${(analysis.similarityScore * 100).toFixed(1)}%)`);
|
|
132
|
+
}
|
|
133
|
+
else if (analysis.overallStatus === "warning") {
|
|
134
|
+
hasMinorDifferences = true;
|
|
135
|
+
console.log(` ⚠️ Minor differences (${(analysis.similarityScore * 100).toFixed(1)}%)`);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
console.log(` ✅ Consistent (${(analysis.similarityScore * 100).toFixed(1)}%)`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const overallStatus = hasMajorDifferences
|
|
143
|
+
? "major_differences"
|
|
144
|
+
: hasMinorDifferences
|
|
145
|
+
? "minor_differences"
|
|
146
|
+
: "consistent";
|
|
147
|
+
const summary = overallStatus === "consistent"
|
|
148
|
+
? "Page renders consistently across all tested browsers"
|
|
149
|
+
: overallStatus === "minor_differences"
|
|
150
|
+
? "Minor rendering differences detected between browsers"
|
|
151
|
+
: "Significant rendering differences detected between browsers";
|
|
152
|
+
return {
|
|
153
|
+
url,
|
|
154
|
+
screenshots,
|
|
155
|
+
comparisons,
|
|
156
|
+
overallStatus,
|
|
157
|
+
summary,
|
|
158
|
+
problematicBrowsers: Array.from(problematicBrowsers),
|
|
159
|
+
duration: Date.now() - startTime,
|
|
160
|
+
timestamp: new Date().toISOString(),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Run cross-browser test suite
|
|
165
|
+
*/
|
|
166
|
+
async function runCrossBrowserSuite(suite) {
|
|
167
|
+
const startTime = Date.now();
|
|
168
|
+
const results = [];
|
|
169
|
+
let consistent = 0;
|
|
170
|
+
let minorDifferences = 0;
|
|
171
|
+
let majorDifferences = 0;
|
|
172
|
+
console.log(`\n🌐 Cross-Browser Visual Test Suite: ${suite.name}`);
|
|
173
|
+
console.log(` Testing ${suite.urls.length} URL(s)...\n`);
|
|
174
|
+
for (const url of suite.urls) {
|
|
175
|
+
const result = await runCrossBrowserTest(url, suite.options);
|
|
176
|
+
results.push(result);
|
|
177
|
+
switch (result.overallStatus) {
|
|
178
|
+
case "consistent":
|
|
179
|
+
consistent++;
|
|
180
|
+
break;
|
|
181
|
+
case "minor_differences":
|
|
182
|
+
minorDifferences++;
|
|
183
|
+
break;
|
|
184
|
+
case "major_differences":
|
|
185
|
+
majorDifferences++;
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
suite,
|
|
191
|
+
results,
|
|
192
|
+
summary: {
|
|
193
|
+
total: suite.urls.length,
|
|
194
|
+
consistent,
|
|
195
|
+
minorDifferences,
|
|
196
|
+
majorDifferences,
|
|
197
|
+
},
|
|
198
|
+
duration: Date.now() - startTime,
|
|
199
|
+
timestamp: new Date().toISOString(),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Format cross-browser result as text report
|
|
204
|
+
*/
|
|
205
|
+
function formatCrossBrowserReport(result) {
|
|
206
|
+
const lines = [];
|
|
207
|
+
lines.push("╔══════════════════════════════════════════════════════════════════════════════╗");
|
|
208
|
+
lines.push("║ CROSS-BROWSER VISUAL TEST REPORT ║");
|
|
209
|
+
lines.push("╚══════════════════════════════════════════════════════════════════════════════╝");
|
|
210
|
+
lines.push("");
|
|
211
|
+
const statusIcon = {
|
|
212
|
+
consistent: "✅",
|
|
213
|
+
minor_differences: "⚠️",
|
|
214
|
+
major_differences: "❌",
|
|
215
|
+
}[result.overallStatus];
|
|
216
|
+
const statusText = {
|
|
217
|
+
consistent: "CONSISTENT",
|
|
218
|
+
minor_differences: "MINOR DIFFERENCES",
|
|
219
|
+
major_differences: "MAJOR DIFFERENCES",
|
|
220
|
+
}[result.overallStatus];
|
|
221
|
+
lines.push(`${statusIcon} Status: ${statusText}`);
|
|
222
|
+
lines.push(`🔗 URL: ${result.url}`);
|
|
223
|
+
lines.push(`⏱️ Duration: ${(result.duration / 1000).toFixed(2)}s`);
|
|
224
|
+
lines.push("");
|
|
225
|
+
lines.push("───────────────────────────────────────────────────────────────────────────────");
|
|
226
|
+
lines.push("📸 BROWSER SCREENSHOTS");
|
|
227
|
+
lines.push("───────────────────────────────────────────────────────────────────────────────");
|
|
228
|
+
for (const screenshot of result.screenshots) {
|
|
229
|
+
lines.push(` ${screenshot.browser.toUpperCase()}`);
|
|
230
|
+
lines.push(` Viewport: ${screenshot.viewport.width}x${screenshot.viewport.height}`);
|
|
231
|
+
lines.push(` Capture time: ${screenshot.captureTime}ms`);
|
|
232
|
+
lines.push(` Path: ${screenshot.screenshotPath}`);
|
|
233
|
+
lines.push("");
|
|
234
|
+
}
|
|
235
|
+
lines.push("───────────────────────────────────────────────────────────────────────────────");
|
|
236
|
+
lines.push("🔍 BROWSER COMPARISONS");
|
|
237
|
+
lines.push("───────────────────────────────────────────────────────────────────────────────");
|
|
238
|
+
for (const comparison of result.comparisons) {
|
|
239
|
+
const compIcon = {
|
|
240
|
+
pass: "✅",
|
|
241
|
+
warning: "⚠️",
|
|
242
|
+
fail: "❌",
|
|
243
|
+
}[comparison.analysis.overallStatus];
|
|
244
|
+
lines.push(` ${comparison.browserA.toUpperCase()} vs ${comparison.browserB.toUpperCase()}: ${compIcon}`);
|
|
245
|
+
lines.push(` Similarity: ${(comparison.analysis.similarityScore * 100).toFixed(1)}%`);
|
|
246
|
+
lines.push(` ${comparison.analysis.summary}`);
|
|
247
|
+
if (comparison.analysis.changes.length > 0) {
|
|
248
|
+
for (const change of comparison.analysis.changes) {
|
|
249
|
+
lines.push(` - [${change.severity.toUpperCase()}] ${change.description}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
lines.push("");
|
|
253
|
+
}
|
|
254
|
+
if (result.problematicBrowsers.length > 0) {
|
|
255
|
+
lines.push("───────────────────────────────────────────────────────────────────────────────");
|
|
256
|
+
lines.push("⚠️ BROWSERS WITH ISSUES");
|
|
257
|
+
lines.push("───────────────────────────────────────────────────────────────────────────────");
|
|
258
|
+
for (const browser of result.problematicBrowsers) {
|
|
259
|
+
lines.push(` • ${browser}`);
|
|
260
|
+
}
|
|
261
|
+
lines.push("");
|
|
262
|
+
}
|
|
263
|
+
lines.push("───────────────────────────────────────────────────────────────────────────────");
|
|
264
|
+
lines.push(`📝 SUMMARY: ${result.summary}`);
|
|
265
|
+
lines.push("───────────────────────────────────────────────────────────────────────────────");
|
|
266
|
+
return lines.join("\n");
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Generate HTML report for cross-browser test suite
|
|
270
|
+
*/
|
|
271
|
+
function generateCrossBrowserHtmlReport(suiteResult) {
|
|
272
|
+
const { suite, results, summary, duration, timestamp } = suiteResult;
|
|
273
|
+
return `<!DOCTYPE html>
|
|
274
|
+
<html lang="en">
|
|
275
|
+
<head>
|
|
276
|
+
<meta charset="UTF-8">
|
|
277
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
278
|
+
<title>Cross-Browser Visual Report - ${suite.name}</title>
|
|
279
|
+
<style>
|
|
280
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
281
|
+
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0f172a; color: #e2e8f0; line-height: 1.6; }
|
|
282
|
+
.container { max-width: 1400px; margin: 0 auto; padding: 2rem; }
|
|
283
|
+
h1 { font-size: 2rem; margin-bottom: 0.5rem; }
|
|
284
|
+
h2 { font-size: 1.25rem; margin-bottom: 1rem; color: #94a3b8; }
|
|
285
|
+
.header { text-align: center; margin-bottom: 2rem; }
|
|
286
|
+
.summary { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 2rem; }
|
|
287
|
+
.stat { background: #1e293b; padding: 1.5rem; border-radius: 0.5rem; text-align: center; }
|
|
288
|
+
.stat-value { font-size: 2rem; font-weight: bold; }
|
|
289
|
+
.stat-label { color: #94a3b8; font-size: 0.875rem; }
|
|
290
|
+
.consistent { color: #22c55e; }
|
|
291
|
+
.minor { color: #eab308; }
|
|
292
|
+
.major { color: #ef4444; }
|
|
293
|
+
.results { display: flex; flex-direction: column; gap: 2rem; }
|
|
294
|
+
.result-card { background: #1e293b; border-radius: 0.5rem; overflow: hidden; }
|
|
295
|
+
.result-header { padding: 1rem; border-bottom: 1px solid #334155; display: flex; justify-content: space-between; align-items: center; }
|
|
296
|
+
.result-body { padding: 1rem; }
|
|
297
|
+
.screenshots { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1rem; margin-bottom: 1rem; }
|
|
298
|
+
.screenshot-card { background: #0f172a; border-radius: 0.25rem; padding: 1rem; text-align: center; }
|
|
299
|
+
.screenshot-card img { max-width: 100%; border-radius: 0.25rem; margin-top: 0.5rem; }
|
|
300
|
+
.browser-name { font-weight: bold; text-transform: capitalize; }
|
|
301
|
+
.comparisons { margin-top: 1rem; }
|
|
302
|
+
.comparison { padding: 0.75rem; background: #0f172a; border-radius: 0.25rem; margin-bottom: 0.5rem; }
|
|
303
|
+
.comparison-header { display: flex; justify-content: space-between; align-items: center; }
|
|
304
|
+
.badge { padding: 0.25rem 0.75rem; border-radius: 9999px; font-size: 0.75rem; font-weight: 600; }
|
|
305
|
+
.badge-consistent { background: #166534; color: #22c55e; }
|
|
306
|
+
.badge-minor { background: #713f12; color: #eab308; }
|
|
307
|
+
.badge-major { background: #7f1d1d; color: #ef4444; }
|
|
308
|
+
footer { text-align: center; color: #64748b; margin-top: 2rem; padding-top: 2rem; border-top: 1px solid #334155; }
|
|
309
|
+
</style>
|
|
310
|
+
</head>
|
|
311
|
+
<body>
|
|
312
|
+
<div class="container">
|
|
313
|
+
<div class="header">
|
|
314
|
+
<h1>🌐 Cross-Browser Visual Report</h1>
|
|
315
|
+
<h2>${suite.name}</h2>
|
|
316
|
+
<p style="color: #64748b;">Generated: ${new Date(timestamp).toLocaleString()}</p>
|
|
317
|
+
</div>
|
|
318
|
+
|
|
319
|
+
<div class="summary">
|
|
320
|
+
<div class="stat">
|
|
321
|
+
<div class="stat-value">${summary.total}</div>
|
|
322
|
+
<div class="stat-label">URLs Tested</div>
|
|
323
|
+
</div>
|
|
324
|
+
<div class="stat">
|
|
325
|
+
<div class="stat-value consistent">${summary.consistent}</div>
|
|
326
|
+
<div class="stat-label">Consistent</div>
|
|
327
|
+
</div>
|
|
328
|
+
<div class="stat">
|
|
329
|
+
<div class="stat-value minor">${summary.minorDifferences}</div>
|
|
330
|
+
<div class="stat-label">Minor Differences</div>
|
|
331
|
+
</div>
|
|
332
|
+
<div class="stat">
|
|
333
|
+
<div class="stat-value major">${summary.majorDifferences}</div>
|
|
334
|
+
<div class="stat-label">Major Differences</div>
|
|
335
|
+
</div>
|
|
336
|
+
</div>
|
|
337
|
+
|
|
338
|
+
<div class="results">
|
|
339
|
+
${results.map(result => {
|
|
340
|
+
const statusClass = result.overallStatus === "consistent" ? "consistent" : result.overallStatus === "minor_differences" ? "minor" : "major";
|
|
341
|
+
const badgeClass = result.overallStatus === "consistent" ? "badge-consistent" : result.overallStatus === "minor_differences" ? "badge-minor" : "badge-major";
|
|
342
|
+
const statusText = result.overallStatus === "consistent" ? "Consistent" : result.overallStatus === "minor_differences" ? "Minor Differences" : "Major Differences";
|
|
343
|
+
return `
|
|
344
|
+
<div class="result-card">
|
|
345
|
+
<div class="result-header">
|
|
346
|
+
<div>
|
|
347
|
+
<strong>${result.url}</strong>
|
|
348
|
+
<div style="color: #64748b; font-size: 0.875rem;">${result.summary}</div>
|
|
349
|
+
</div>
|
|
350
|
+
<span class="badge ${badgeClass}">${statusText}</span>
|
|
351
|
+
</div>
|
|
352
|
+
<div class="result-body">
|
|
353
|
+
<h3 style="margin-bottom: 1rem; color: #94a3b8;">Screenshots</h3>
|
|
354
|
+
<div class="screenshots">
|
|
355
|
+
${result.screenshots.map(s => `
|
|
356
|
+
<div class="screenshot-card">
|
|
357
|
+
<div class="browser-name">${s.browser}</div>
|
|
358
|
+
<div style="color: #64748b; font-size: 0.75rem;">${s.viewport.width}x${s.viewport.height} • ${s.captureTime}ms</div>
|
|
359
|
+
</div>
|
|
360
|
+
`).join("")}
|
|
361
|
+
</div>
|
|
362
|
+
|
|
363
|
+
<h3 style="margin: 1rem 0; color: #94a3b8;">Comparisons</h3>
|
|
364
|
+
<div class="comparisons">
|
|
365
|
+
${result.comparisons.map(c => {
|
|
366
|
+
const cBadgeClass = c.analysis.overallStatus === "pass" ? "badge-consistent" : c.analysis.overallStatus === "warning" ? "badge-minor" : "badge-major";
|
|
367
|
+
return `
|
|
368
|
+
<div class="comparison">
|
|
369
|
+
<div class="comparison-header">
|
|
370
|
+
<span>${c.browserA} vs ${c.browserB}</span>
|
|
371
|
+
<span class="badge ${cBadgeClass}">${(c.analysis.similarityScore * 100).toFixed(1)}%</span>
|
|
372
|
+
</div>
|
|
373
|
+
<p style="color: #94a3b8; font-size: 0.875rem; margin-top: 0.5rem;">${c.analysis.summary}</p>
|
|
374
|
+
</div>
|
|
375
|
+
`;
|
|
376
|
+
}).join("")}
|
|
377
|
+
</div>
|
|
378
|
+
</div>
|
|
379
|
+
</div>
|
|
380
|
+
`;
|
|
381
|
+
}).join("")}
|
|
382
|
+
</div>
|
|
383
|
+
|
|
384
|
+
<footer>
|
|
385
|
+
Generated by CBrowser v7.2.0 | Test completed in ${(duration / 1000).toFixed(1)}s
|
|
386
|
+
</footer>
|
|
387
|
+
</div>
|
|
388
|
+
</body>
|
|
389
|
+
</html>`;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Compare page behavior across multiple browsers.
|
|
393
|
+
*/
|
|
394
|
+
async function crossBrowserDiff(url, browsers = ["chromium", "firefox", "webkit"]) {
|
|
395
|
+
const { chromium, firefox, webkit } = await import("playwright");
|
|
396
|
+
const screenshots = {};
|
|
397
|
+
const metrics = {};
|
|
398
|
+
const differences = [];
|
|
399
|
+
const contents = {};
|
|
400
|
+
const browserLaunchers = { chromium, firefox, webkit };
|
|
401
|
+
for (const browserName of browsers) {
|
|
402
|
+
const launcher = browserLaunchers[browserName];
|
|
403
|
+
const browser = await launcher.launch({ headless: true });
|
|
404
|
+
const page = await browser.newPage();
|
|
405
|
+
const startTime = Date.now();
|
|
406
|
+
await page.goto(url, { waitUntil: "domcontentloaded" });
|
|
407
|
+
const loadTime = Date.now() - startTime;
|
|
408
|
+
// Capture metrics
|
|
409
|
+
const resourceCount = await page.evaluate(() => performance.getEntriesByType("resource").length);
|
|
410
|
+
metrics[browserName] = { loadTime, resourceCount };
|
|
411
|
+
// Capture screenshot
|
|
412
|
+
const screenshotPath = `/tmp/cross-browser-${browserName}-${Date.now()}.png`;
|
|
413
|
+
await page.screenshot({ path: screenshotPath, fullPage: true });
|
|
414
|
+
screenshots[browserName] = screenshotPath;
|
|
415
|
+
// Capture content hash
|
|
416
|
+
contents[browserName] = await page.evaluate(() => document.body.innerText.slice(0, 1000));
|
|
417
|
+
await browser.close();
|
|
418
|
+
}
|
|
419
|
+
// Compare timing
|
|
420
|
+
const loadTimes = Object.entries(metrics).map(([b, m]) => ({ browser: b, time: m.loadTime }));
|
|
421
|
+
const avgTime = loadTimes.reduce((sum, t) => sum + t.time, 0) / loadTimes.length;
|
|
422
|
+
const slowBrowsers = loadTimes.filter(t => t.time > avgTime * 1.5);
|
|
423
|
+
if (slowBrowsers.length > 0) {
|
|
424
|
+
differences.push({
|
|
425
|
+
type: "timing",
|
|
426
|
+
description: `Significantly slower in: ${slowBrowsers.map(b => `${b.browser} (${b.time}ms)`).join(", ")}`,
|
|
427
|
+
browsers: slowBrowsers.map(b => b.browser),
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
// Compare content
|
|
431
|
+
const contentValues = Object.values(contents);
|
|
432
|
+
const contentMismatch = contentValues.some(c => c !== contentValues[0]);
|
|
433
|
+
if (contentMismatch) {
|
|
434
|
+
differences.push({
|
|
435
|
+
type: "content",
|
|
436
|
+
description: "Page content differs between browsers",
|
|
437
|
+
browsers,
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
return { url, browsers, differences, screenshots, metrics };
|
|
441
|
+
}
|
|
442
|
+
//# sourceMappingURL=cross-browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-browser.js","sourceRoot":"","sources":["../../src/visual/cross-browser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual Testing Module
|
|
3
|
+
*
|
|
4
|
+
* AI-powered visual regression, cross-browser, responsive, and A/B comparison testing.
|
|
5
|
+
*/
|
|
6
|
+
export * from "./regression.js";
|
|
7
|
+
export * from "./cross-browser.js";
|
|
8
|
+
export * from "./responsive.js";
|
|
9
|
+
export * from "./ab-comparison.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/visual/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Visual Testing Module
|
|
4
|
+
*
|
|
5
|
+
* AI-powered visual regression, cross-browser, responsive, and A/B comparison testing.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
__exportStar(require("./regression.js"), exports);
|
|
23
|
+
__exportStar(require("./cross-browser.js"), exports);
|
|
24
|
+
__exportStar(require("./responsive.js"), exports);
|
|
25
|
+
__exportStar(require("./ab-comparison.js"), exports);
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/visual/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;AAEH,kDAAgC;AAChC,qDAAmC;AACnC,kDAAgC;AAChC,qDAAmC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Visual Regression Testing (v7.0.0)
|
|
3
|
+
*
|
|
4
|
+
* Capture baselines and compare screenshots using AI-powered analysis.
|
|
5
|
+
*/
|
|
6
|
+
import type { VisualBaseline, AIVisualAnalysis, VisualRegressionResult, VisualRegressionOptions, VisualTestSuite, VisualTestSuiteResult } from "../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Load all visual baselines from storage
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadVisualBaselines(): VisualBaseline[];
|
|
11
|
+
/**
|
|
12
|
+
* Capture a visual baseline screenshot
|
|
13
|
+
*/
|
|
14
|
+
export declare function captureVisualBaseline(url: string, name: string, options?: {
|
|
15
|
+
selector?: string;
|
|
16
|
+
device?: string;
|
|
17
|
+
viewport?: {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
};
|
|
21
|
+
waitFor?: string | number;
|
|
22
|
+
}): Promise<VisualBaseline>;
|
|
23
|
+
/**
|
|
24
|
+
* List all visual baselines
|
|
25
|
+
*/
|
|
26
|
+
export declare function listVisualBaselines(): VisualBaseline[];
|
|
27
|
+
/**
|
|
28
|
+
* Get a visual baseline by name
|
|
29
|
+
*/
|
|
30
|
+
export declare function getVisualBaseline(name: string): VisualBaseline | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Delete a visual baseline
|
|
33
|
+
*/
|
|
34
|
+
export declare function deleteVisualBaseline(name: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Analyze visual differences using AI
|
|
37
|
+
*/
|
|
38
|
+
export declare function analyzeVisualDifferences(baselinePath: string, currentPath: string, options?: VisualRegressionOptions): Promise<AIVisualAnalysis>;
|
|
39
|
+
/**
|
|
40
|
+
* Run visual regression test against a baseline
|
|
41
|
+
*/
|
|
42
|
+
export declare function runVisualRegression(url: string, baselineName: string, options?: VisualRegressionOptions): Promise<VisualRegressionResult>;
|
|
43
|
+
/**
|
|
44
|
+
* Run visual regression on multiple pages
|
|
45
|
+
*/
|
|
46
|
+
export declare function runVisualRegressionSuite(suite: VisualTestSuite, options?: VisualRegressionOptions): Promise<VisualTestSuiteResult>;
|
|
47
|
+
/**
|
|
48
|
+
* Format visual regression result as text report
|
|
49
|
+
*/
|
|
50
|
+
export declare function formatVisualRegressionReport(result: VisualRegressionResult): string;
|
|
51
|
+
/**
|
|
52
|
+
* Generate HTML report for visual regression suite
|
|
53
|
+
*/
|
|
54
|
+
export declare function generateVisualRegressionHtmlReport(suiteResult: VisualTestSuiteResult): string;
|
|
55
|
+
//# sourceMappingURL=regression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regression.d.ts","sourceRoot":"","sources":["../../src/visual/regression.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EACV,cAAc,EAEd,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,qBAAqB,EACtB,MAAM,aAAa,CAAC;AA0BrB;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,EAAE,CActD;AAYD;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACtB,GACL,OAAO,CAAC,cAAc,CAAC,CA6DzB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,EAAE,CAEtD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAG1E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAkB1D;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,gBAAgB,CAAC,CAgG3B;AAsFD;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC,CAyEjC;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,eAAe,EACtB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,qBAAqB,CAAC,CAsDhC;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAkEnF;AAED;;GAEG;AACH,wBAAgB,kCAAkC,CAAC,WAAW,EAAE,qBAAqB,GAAG,MAAM,CAgH7F"}
|