openspec-playwright 0.3.46 → 0.3.48

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.
@@ -1,351 +0,0 @@
1
- /**
2
- * Vision check command: Analyze screenshots for layout anomalies using Ollama VLM.
3
- *
4
- * Modes:
5
- * --screenshots "..." Analyze existing files (single mode)
6
- * --url ... --viewport ... Capture from URL at multiple viewports
7
- * --baseline Save as baseline (with --screenshots or --url+viewport)
8
- * --diff Compare against baseline
9
- * --report <path> Generate HTML report
10
- *
11
- * Exit codes:
12
- * 0 = Check completed (with or without anomalies)
13
- * 1 = Ollama not available (skipped)
14
- * 2 = Configuration missing or invalid (skipped)
15
- */
16
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
17
- import { join, basename } from "path";
18
- import { glob } from "glob";
19
- import chalk from "chalk";
20
- import { chromium } from "playwright";
21
- import { loadOllamaConfig, checkOllamaHealth, batchAnalyzeScreenshots, compareScreenshotDiff, generateHtmlReport, } from "../utils/ollama.js";
22
- /**
23
- * Extract route name from screenshot path.
24
- * e.g., "__screenshots__/dashboard.png" → "/dashboard"
25
- * "__screenshots__/settings-profile.png" → "/settings/profile"
26
- */
27
- function extractRouteFromPath(screenshotPath) {
28
- const name = basename(screenshotPath, ".png");
29
- // Convert dashes back to slashes, handle root
30
- if (name === "index" || name === "home" || name === "root") {
31
- return "/";
32
- }
33
- return "/" + name.replace(/-/g, "/");
34
- }
35
- /**
36
- * Resolve screenshot paths from glob or comma-separated list.
37
- */
38
- async function resolveScreenshots(pattern) {
39
- // Check if comma-separated list
40
- if (pattern.includes(",") && !pattern.includes("*")) {
41
- return pattern.split(",").map((p) => ({
42
- path: p.trim(),
43
- route: extractRouteFromPath(p.trim()),
44
- }));
45
- }
46
- // Glob pattern
47
- const paths = await glob(pattern, { absolute: true });
48
- return paths.map((p) => ({
49
- path: p,
50
- route: extractRouteFromPath(p),
51
- }));
52
- }
53
- /**
54
- * Filter anomalies by severity level.
55
- */
56
- function filterBySeverity(anomalies, severityFilter) {
57
- const levels = severityFilter.toLowerCase().split(",").map((s) => s.trim());
58
- return anomalies.filter((a) => levels.includes(a.severity));
59
- }
60
- // ── Viewport presets ───────────────────────────────────────────────────────────
61
- const VIEWPORT_PRESETS = {
62
- mobile: { width: 375, height: 667 },
63
- tablet: { width: 768, height: 1024 },
64
- desktop: { width: 1280, height: 720 },
65
- wide: { width: 1920, height: 1080 },
66
- };
67
- /**
68
- * Parse viewport string: "mobile,desktop" or "375x667,1280x720"
69
- */
70
- function parseViewports(input) {
71
- return input.split(",").map((v) => {
72
- const name = v.trim().toLowerCase();
73
- if (VIEWPORT_PRESETS[name]) {
74
- return { name, ...VIEWPORT_PRESETS[name] };
75
- }
76
- const parts = name.split("x");
77
- if (parts.length === 2) {
78
- const w = parseInt(parts[0], 10);
79
- const h = parseInt(parts[1], 10);
80
- if (w > 0 && h > 0) {
81
- return { name: `${w}x${h}`, width: w, height: h };
82
- }
83
- }
84
- throw new Error(`Invalid viewport: "${v}". Use presets (mobile/tablet/desktop/wide) or WxH (e.g. 375x667)`);
85
- });
86
- }
87
- // ── Baseline paths ───────────────────────────────────────────────────────────
88
- const BASELINE_DIR = ".openspec-pw/vision-baseline";
89
- const DIFF_DIR = ".openspec-pw/vision-diff";
90
- /**
91
- * Capture screenshots from a URL at multiple viewports using Playwright.
92
- */
93
- async function captureFromUrl(url, viewports, outputDir, concurrency = 2) {
94
- const results = [];
95
- mkdirSync(outputDir, { recursive: true });
96
- let browser = null;
97
- try {
98
- browser = await chromium.launch({ headless: true });
99
- for (let i = 0; i < viewports.length; i += concurrency) {
100
- const batch = viewports.slice(i, i + concurrency);
101
- const batchPromises = batch.map(async (vp) => {
102
- // Each viewport gets its own context so viewport size doesn't affect other captures
103
- const context = await browser.newContext({
104
- viewport: { width: vp.width, height: vp.height },
105
- });
106
- const page = await context.newPage();
107
- try {
108
- await page.goto(url, { waitUntil: "networkidle", timeout: 30000 });
109
- const filename = `${vp.name}.png`;
110
- const filepath = join(outputDir, filename);
111
- await page.screenshot({ path: filepath, fullPage: true });
112
- return { path: filepath, route: `${vp.name}:${url}`, viewport: vp.name };
113
- }
114
- finally {
115
- await context.close();
116
- }
117
- });
118
- const batchResults = await Promise.all(batchPromises);
119
- results.push(...batchResults);
120
- }
121
- }
122
- finally {
123
- if (browser)
124
- await browser.close();
125
- }
126
- return results;
127
- }
128
- /**
129
- * Copy screenshots to baseline directory.
130
- */
131
- function saveBaseline(screenshots, projectRoot) {
132
- const baselineDir = join(projectRoot, BASELINE_DIR);
133
- mkdirSync(baselineDir, { recursive: true });
134
- for (const s of screenshots) {
135
- const base = basename(s.path, ".png");
136
- const name = s.viewport
137
- ? `${base}-${s.viewport}-baseline.png`
138
- : `${base}-baseline.png`;
139
- const dest = join(baselineDir, name);
140
- writeFileSync(dest, readFileSync(s.path));
141
- console.log(chalk.green(` ✓ Baseline saved: ${dest}`));
142
- }
143
- return baselineDir;
144
- }
145
- // ── Main command ─────────────────────────────────────────────────────────────
146
- /**
147
- * Main vision check command.
148
- */
149
- export async function visionCheck(options) {
150
- const projectRoot = process.cwd();
151
- // 0. Validate required arguments
152
- if (!options.screenshots && !(options.viewport && options.url)) {
153
- console.log(chalk.yellow("Error: Provide --screenshots <pattern> or --url <url> --viewport <views>"));
154
- process.exit(2);
155
- }
156
- // 1. Validate threshold
157
- if (options.threshold !== undefined && (options.threshold < 0 || options.threshold > 1)) {
158
- console.log(chalk.yellow("Error: --threshold must be between 0 and 1"));
159
- process.exit(2);
160
- }
161
- // 2. Load configuration
162
- const config = loadOllamaConfig(projectRoot);
163
- if (!config.enabled) {
164
- const result = {
165
- processed: 0,
166
- anomalies: [],
167
- skipped: [],
168
- skipReason: "disabled",
169
- ollamaUrl: config.url,
170
- model: config.model,
171
- };
172
- if (options.json) {
173
- console.log(JSON.stringify(result, null, 2));
174
- }
175
- else {
176
- console.log(chalk.yellow("Vision check disabled in config"));
177
- }
178
- process.exit(2);
179
- }
180
- // 3. Parse viewports
181
- let viewports = null;
182
- if (options.viewport) {
183
- viewports = parseViewports(options.viewport);
184
- }
185
- // 4. Gather screenshots
186
- let screenshots = [];
187
- if (options.viewport && options.url) {
188
- // Multi-viewport capture mode
189
- if (!options.json) {
190
- console.log(chalk.blue(`\n📷 Capturing at ${viewports.length} viewport(s) from ${options.url}...\n`));
191
- }
192
- screenshots = await captureFromUrl(options.url, viewports, join(projectRoot, ".openspec-pw/vision-current"));
193
- }
194
- else {
195
- // File-based mode
196
- screenshots = await resolveScreenshots(options.screenshots);
197
- }
198
- if (screenshots.length === 0) {
199
- console.log(chalk.yellow("No screenshots found matching the provided pattern"));
200
- process.exit(1);
201
- }
202
- // 5. Baseline mode: save and exit
203
- if (options.baseline) {
204
- const baselineDir = saveBaseline(screenshots, projectRoot);
205
- if (!options.json) {
206
- console.log(chalk.green(`\n✓ Baseline saved (${screenshots.length} screenshots) in ${baselineDir}`));
207
- }
208
- return;
209
- }
210
- // 6. Dry run
211
- if (options.dryRun) {
212
- console.log(chalk.blue("\n📷 Screenshots (dry run):\n"));
213
- for (const s of screenshots) {
214
- const vp = s.viewport ? ` [${s.viewport}]` : "";
215
- console.log(` ${s.route}${vp} → ${s.path}`);
216
- }
217
- console.log(chalk.gray(`\nTotal: ${screenshots.length} files`));
218
- console.log(chalk.gray(`Ollama: ${config.url} (${config.model})`));
219
- return;
220
- }
221
- // 7. Health check
222
- const health = await checkOllamaHealth(config);
223
- if (!health.ok) {
224
- const result = {
225
- processed: 0,
226
- anomalies: [],
227
- skipped: [],
228
- skipReason: health.message,
229
- ollamaUrl: config.url,
230
- model: config.model,
231
- };
232
- if (options.json) {
233
- console.log(JSON.stringify(result, null, 2));
234
- }
235
- else {
236
- console.log(chalk.yellow(`Vision check skipped: ${health.message}`));
237
- }
238
- process.exit(1);
239
- }
240
- if (!options.json) {
241
- const mode = options.diff ? "diff" : "analyze";
242
- console.log(chalk.blue(`\n🔍 ${mode === "diff" ? "Pixel diff" : "Analyzing"} ${screenshots.length} screenshot(s)...\n`));
243
- }
244
- // 8. Diff mode: compare with baseline
245
- const result = {
246
- processed: 0,
247
- anomalies: [],
248
- skipped: [],
249
- ollamaUrl: config.url,
250
- model: config.model,
251
- baselineDir: join(projectRoot, BASELINE_DIR),
252
- };
253
- if (options.diff) {
254
- const baselineDir = join(projectRoot, BASELINE_DIR);
255
- const diffDir = join(projectRoot, DIFF_DIR);
256
- mkdirSync(diffDir, { recursive: true });
257
- for (const s of screenshots) {
258
- const baseName = basename(s.path, ".png");
259
- const baselineSuffix = s.viewport ? `-${s.viewport}-baseline` : "-baseline";
260
- const baselinePath = join(baselineDir, `${baseName}${baselineSuffix}.png`);
261
- const diffPath = join(diffDir, `${baseName}-diff.png`);
262
- if (!existsSync(baselinePath)) {
263
- result.skipped.push(s.path);
264
- if (!options.json) {
265
- console.log(chalk.yellow(` ⚠ No baseline for ${s.route}, skipping diff`));
266
- }
267
- continue;
268
- }
269
- try {
270
- const { changed, anomalies } = await compareScreenshotDiff(config, baselinePath, s.path, diffPath, s.route, options.threshold ?? 0.1);
271
- result.processed++;
272
- result.anomalies.push(...anomalies.map((a) => ({ ...a, viewport: s.viewport })));
273
- if (!options.json) {
274
- if (changed) {
275
- console.log(chalk.yellow(` ~ ${s.route}${s.viewport ? ` [${s.viewport}]` : ""}: ${anomalies.length} anomaly(ies)`));
276
- }
277
- else {
278
- console.log(chalk.gray(` ✓ ${s.route}${s.viewport ? ` [${s.viewport}]` : ""}: no changes`));
279
- }
280
- }
281
- }
282
- catch (err) {
283
- const error = err;
284
- result.skipped.push(s.path);
285
- if (!options.json) {
286
- console.error(chalk.red(` ✗ ${s.route}: ${error.message}`));
287
- }
288
- }
289
- }
290
- }
291
- else {
292
- // Analyze mode: batch analyze screenshots
293
- const concurrency = options.parallel || 4;
294
- const batchResult = await batchAnalyzeScreenshots(config, screenshots.map((s) => ({ path: s.path, route: s.route })), concurrency, options.noCache);
295
- result.processed = batchResult.processed;
296
- result.anomalies = batchResult.anomalies.map((a) => ({
297
- ...a,
298
- viewport: screenshots.find((s) => s.path === a.screenshot)?.viewport,
299
- }));
300
- result.skipped = batchResult.skipped;
301
- }
302
- // 9. Filter by severity
303
- if (options.severity) {
304
- result.anomalies = filterBySeverity(result.anomalies, options.severity);
305
- }
306
- // 10. Output
307
- if (options.json) {
308
- console.log(JSON.stringify(result, null, 2));
309
- }
310
- else {
311
- console.log(chalk.blue("─── Results ───\n"));
312
- console.log(` Processed: ${result.processed}/${screenshots.length}`);
313
- console.log(` Anomalies: ${result.anomalies.length}`);
314
- if (result.skipped.length > 0) {
315
- console.log(chalk.yellow(` Skipped: ${result.skipped.length}`));
316
- }
317
- if (result.anomalies.length > 0) {
318
- console.log(chalk.blue("\n─── Anomalies ───\n"));
319
- for (const a of result.anomalies) {
320
- const severityColor = a.severity === "blocking"
321
- ? chalk.red
322
- : a.severity === "warning"
323
- ? chalk.yellow
324
- : chalk.gray;
325
- const vp = a.viewport ? ` [${a.viewport}]` : "";
326
- console.log(` ${severityColor(`[${a.severity}]`)} ${a.route}${vp}`);
327
- console.log(` Element: ${a.element}`);
328
- console.log(` Type: ${a.type} (${a.position})`);
329
- console.log(` ${a.description}\n`);
330
- }
331
- }
332
- else {
333
- console.log(chalk.green("\n ✓ No layout anomalies detected\n"));
334
- }
335
- }
336
- // 11. HTML report
337
- if (options.report) {
338
- generateHtmlReport(result, screenshots.map((s) => ({ path: s.path, route: s.route })), options.report, options.diff ? join(projectRoot, DIFF_DIR) : undefined);
339
- if (!options.json) {
340
- console.log(chalk.green(` ✓ HTML report: ${options.report}`));
341
- }
342
- }
343
- // 12. JSON output file
344
- if (options.output) {
345
- writeFileSync(options.output, JSON.stringify(result, null, 2), "utf-8");
346
- if (!options.json) {
347
- console.log(chalk.green(` ✓ Results written to ${options.output}`));
348
- }
349
- }
350
- }
351
- //# sourceMappingURL=visionCheck.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"visionCheck.js","sourceRoot":"","sources":["../../src/commands/visionCheck.ts"],"names":[],"mappings":"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"}
@@ -1,73 +0,0 @@
1
- /**
2
- * Ollama API utilities for vision model integration.
3
- *
4
- * Configuration: reads from `.env` in `tests/playwright/` (highest priority),
5
- * then falls back to environment variables. If no URL or model is found,
6
- * vision check is disabled.
7
- */
8
- export interface OllamaConfig {
9
- url: string;
10
- model: string;
11
- enabled: boolean;
12
- }
13
- export interface VisionAnomaly {
14
- route: string;
15
- screenshot: string;
16
- element: string;
17
- type: "obscured" | "crowded" | "overflowed" | "missing" | "incorrect";
18
- position: string;
19
- severity: "blocking" | "warning" | "minor";
20
- description: string;
21
- viewport?: string;
22
- changed?: boolean;
23
- }
24
- export interface VisionCheckResult {
25
- processed: number;
26
- anomalies: VisionAnomaly[];
27
- skipped: string[];
28
- skipReason?: string;
29
- ollamaUrl: string;
30
- model: string;
31
- baselineDir?: string;
32
- currentDir?: string;
33
- }
34
- export interface OllamaGenerateResponse {
35
- response: string;
36
- done: boolean;
37
- }
38
- /**
39
- * Load Ollama config from `.env` in `tests/playwright/` and environment variables.
40
- * If no URL or model is configured, vision check is disabled.
41
- */
42
- export declare function loadOllamaConfig(projectRoot?: string): OllamaConfig;
43
- /**
44
- * Check if Ollama is running and the vision model is available.
45
- * Returns { ok, message } for doctor output.
46
- */
47
- export declare function checkOllamaHealth(config: OllamaConfig): Promise<{
48
- ok: boolean;
49
- message: string;
50
- }>;
51
- /**
52
- * Analyze a single screenshot with the vision model.
53
- */
54
- export declare function analyzeScreenshot(config: OllamaConfig, screenshotPath: string, route: string, prompt?: string, noCache?: boolean): Promise<VisionAnomaly[]>;
55
- /**
56
- * Batch analyze multiple screenshots with concurrency control.
57
- */
58
- export declare function batchAnalyzeScreenshots(config: OllamaConfig, screenshots: Array<{
59
- path: string;
60
- route: string;
61
- }>, concurrency?: number, noCache?: boolean): Promise<VisionCheckResult>;
62
- /**
63
- * Compare two screenshots with pixel diff.
64
- * Returns changed regions and optionally saves a diff image.
65
- */
66
- export declare function compareScreenshotDiff(config: OllamaConfig, baselinePath: string, currentPath: string, diffPath: string, route: string, threshold?: number): Promise<{
67
- changed: boolean;
68
- anomalies: VisionAnomaly[];
69
- }>;
70
- export declare function generateHtmlReport(result: VisionCheckResult, screenshots: Array<{
71
- path: string;
72
- route: string;
73
- }>, outputPath: string, diffDir?: string): void;