openspec-playwright 0.3.47 → 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.
@@ -0,0 +1,311 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ import chalk from "chalk";
4
+ import { SHARED_FILE_NAMES } from "../shared/index.js";
5
+ import { collectSpecFiles } from "./coverage.js";
6
+ // ─── Main Entry Point ─────────────────────────────────────────────────
7
+ export async function flake(changeName, options) {
8
+ const projectRoot = process.cwd();
9
+ const testsDir = join(projectRoot, "tests", "playwright");
10
+ if (!existsSync(testsDir)) {
11
+ console.log(chalk.yellow(" tests/playwright/ not found. Run `openspec-pw init` first.\n"));
12
+ return;
13
+ }
14
+ console.log(chalk.blue("\n🔍 OpenSpec Playwright: Flake Detection\n"));
15
+ // Scope filtering
16
+ let specFiles;
17
+ if (changeName) {
18
+ const changeTestDir = join(testsDir, "changes", changeName);
19
+ if (!existsSync(changeTestDir)) {
20
+ console.log(chalk.yellow(` No tests found for change "${changeName}".\n`));
21
+ return;
22
+ }
23
+ specFiles = collectSpecFiles(changeTestDir);
24
+ }
25
+ else {
26
+ specFiles = collectSpecFiles(testsDir);
27
+ }
28
+ // Filter out shared files
29
+ const SHARED_FILES = new Set([
30
+ ...SHARED_FILE_NAMES,
31
+ "auth.setup.ts",
32
+ "global.teardown.ts",
33
+ "seed.spec.ts",
34
+ ]);
35
+ specFiles = specFiles.filter((f) => {
36
+ const name = f.split("/").pop() ?? "";
37
+ return !SHARED_FILES.has(name);
38
+ });
39
+ if (specFiles.length === 0) {
40
+ console.log(chalk.yellow(" No spec files found to analyze.\n"));
41
+ return;
42
+ }
43
+ // Parse config
44
+ const configHasStorageState = getConfigStorageState(projectRoot);
45
+ // Run all detectors
46
+ const findings = [];
47
+ for (const file of specFiles) {
48
+ const content = readFileSync(file, "utf-8");
49
+ const relPath = file.replace(testsDir + "/", "");
50
+ findings.push(...detectNetworkIdle(content, relPath));
51
+ findings.push(...detectRouteAfterGoto(content, relPath));
52
+ findings.push(...detectStorageLeakage(content, relPath, configHasStorageState));
53
+ findings.push(...detectTestUseScope(content, relPath, configHasStorageState));
54
+ }
55
+ // Build report
56
+ const report = buildReport(findings);
57
+ // Render
58
+ if (options?.json) {
59
+ console.log(JSON.stringify(report, null, 2));
60
+ }
61
+ else {
62
+ renderReport(report);
63
+ }
64
+ // Gate
65
+ if (options?.gate) {
66
+ const exitCode = computeGateExitCode(report, options.gate);
67
+ if (exitCode !== 0)
68
+ process.exit(exitCode);
69
+ }
70
+ }
71
+ // ─── Config Parsing ───────────────────────────────────────────────────
72
+ export function getConfigStorageState(projectRoot) {
73
+ for (const name of [
74
+ "playwright.config.ts",
75
+ "playwright.config.js",
76
+ "playwright.config.mjs",
77
+ ]) {
78
+ const configPath = join(projectRoot, name);
79
+ if (!existsSync(configPath))
80
+ continue;
81
+ const content = readFileSync(configPath, "utf-8");
82
+ if (/storageState/.test(content) || /storageState\s*:/.test(content)) {
83
+ return true;
84
+ }
85
+ }
86
+ return false;
87
+ }
88
+ // ─── Pattern Detectors ────────────────────────────────────────────────
89
+ export function detectNetworkIdle(content, filePath) {
90
+ const findings = [];
91
+ const regex = /waitForLoadState\s*\(\s*['"]networkidle['"]/g;
92
+ let match;
93
+ while ((match = regex.exec(content)) !== null) {
94
+ const line = content.substring(0, match.index).split("\n").length;
95
+ findings.push({
96
+ pattern: "networkidle",
97
+ file: filePath,
98
+ line,
99
+ message: "waitForLoadState('networkidle') in SPA — use a specific response wait instead",
100
+ severity: "high",
101
+ });
102
+ }
103
+ return findings;
104
+ }
105
+ export function detectRouteAfterGoto(content, filePath) {
106
+ const findings = [];
107
+ // Find all test( positions to isolate test blocks
108
+ const testPositions = [];
109
+ const testRegex = /test\s*\(/g;
110
+ let tm;
111
+ while ((tm = testRegex.exec(content)) !== null) {
112
+ testPositions.push(tm.index);
113
+ }
114
+ for (let i = 0; i < testPositions.length; i++) {
115
+ const testStart = testPositions[i];
116
+ const testEnd = i + 1 < testPositions.length ? testPositions[i + 1] : content.length;
117
+ const block = content.substring(testStart, testEnd);
118
+ // Collect page.goto() line numbers
119
+ const gotoCalls = [];
120
+ const gotoRegex = /page\.goto\s*\(/g;
121
+ let gm;
122
+ while ((gm = gotoRegex.exec(block)) !== null) {
123
+ const line = content.substring(0, testStart + gm.index).split("\n").length;
124
+ gotoCalls.push(line);
125
+ }
126
+ // Collect page.route() line numbers (excluding page.context().route())
127
+ const routeCalls = [];
128
+ const routeRegex = /page\.route\s*\(/g;
129
+ let rm;
130
+ while ((rm = routeRegex.exec(block)) !== null) {
131
+ // Skip if this is page.context().route()
132
+ const before = block.substring(Math.max(0, rm.index - 20), rm.index);
133
+ if (before.includes(".context("))
134
+ continue;
135
+ const line = content.substring(0, testStart + rm.index).split("\n").length;
136
+ routeCalls.push(line);
137
+ }
138
+ // If any route call appears after any goto call → finding
139
+ if (routeCalls.length > 0 && gotoCalls.length > 0) {
140
+ const earliestGoto = Math.min(...gotoCalls);
141
+ for (const routeLine of routeCalls) {
142
+ if (routeLine > earliestGoto) {
143
+ findings.push({
144
+ pattern: "route-after-goto",
145
+ file: filePath,
146
+ line: routeLine,
147
+ message: "page.route() registered after page.goto() — move route() before goto()",
148
+ severity: "high",
149
+ });
150
+ }
151
+ }
152
+ }
153
+ }
154
+ return findings;
155
+ }
156
+ export function detectStorageLeakage(content, filePath, configHasStorageState) {
157
+ // Condition 1: file references storageState
158
+ const hasStorageStateRef = content.includes("storageState") || configHasStorageState;
159
+ // Condition 2: page.goto() targeting protected routes
160
+ const protectedRoutes = [
161
+ "/dashboard",
162
+ "/profile",
163
+ "/admin",
164
+ "/settings",
165
+ "/account",
166
+ ];
167
+ const gotoRegex = /page\.goto\s*\(\s*['"`]([^'"`]*)['"`]/g;
168
+ let hasProtectedGoto = false;
169
+ let firstProtectedGotoLine = 0;
170
+ let gm;
171
+ while ((gm = gotoRegex.exec(content)) !== null) {
172
+ const url = gm[1];
173
+ if (protectedRoutes.some((route) => url.includes(route))) {
174
+ hasProtectedGoto = true;
175
+ firstProtectedGotoLine =
176
+ content.substring(0, gm.index).split("\n").length;
177
+ break;
178
+ }
179
+ }
180
+ // Condition 3: no browser.newContext()
181
+ const hasNewContext = content.includes("browser.newContext(");
182
+ if (hasStorageStateRef && hasProtectedGoto && !hasNewContext) {
183
+ return [
184
+ {
185
+ pattern: "storage-leakage",
186
+ file: filePath,
187
+ line: firstProtectedGotoLine,
188
+ message: "Potential storageState leakage — authenticated state may bleed into unauthenticated tests",
189
+ severity: "medium",
190
+ },
191
+ ];
192
+ }
193
+ return [];
194
+ }
195
+ export function detectTestUseScope(content, filePath, configHasStorageState) {
196
+ const findings = [];
197
+ if (!configHasStorageState)
198
+ return findings;
199
+ // Find all test.describe( positions
200
+ const describePositions = [];
201
+ const descRegex = /test\.describe\s*\(/g;
202
+ let dm;
203
+ while ((dm = descRegex.exec(content)) !== null) {
204
+ describePositions.push(dm.index);
205
+ }
206
+ // Find all test.use({ with storageState
207
+ const useRegex = /test\.use\s*\(/g;
208
+ let um;
209
+ while ((um = useRegex.exec(content)) !== null) {
210
+ const usePos = um.index;
211
+ const line = content.substring(0, usePos).split("\n").length;
212
+ // Check if storageState appears nearby (within the test.use config block)
213
+ // Search from usePos to the next test( or test.describe( or end of content
214
+ let searchEnd = content.length;
215
+ const nextTest = content.indexOf("test(", usePos + 1);
216
+ const nextDescribe = content.indexOf("test.describe(", usePos + 1);
217
+ if (nextTest > 0)
218
+ searchEnd = Math.min(searchEnd, nextTest);
219
+ if (nextDescribe > 0)
220
+ searchEnd = Math.min(searchEnd, nextDescribe);
221
+ const context = content.substring(usePos, Math.min(usePos + 500, searchEnd));
222
+ if (!context.includes("storageState"))
223
+ continue;
224
+ // Determine if inside a describe block
225
+ const isInsideDescribe = describePositions.some((dp) => dp < usePos);
226
+ if (isInsideDescribe) {
227
+ // Sub-check 1: test.use({ storageState }) inside test.describe(
228
+ findings.push({
229
+ pattern: "test-use-scope",
230
+ file: filePath,
231
+ line,
232
+ message: "Conflicting test.use({ storageState }) scope — may silently break test isolation",
233
+ severity: "medium",
234
+ });
235
+ }
236
+ else {
237
+ // Sub-check 2: top-level test.use({ storageState }) with untagged tests
238
+ const testTagRegex = /test\(['"`]([^'"`]*)['"`]/g;
239
+ let hasUntaggedTest = false;
240
+ let ttm;
241
+ while ((ttm = testTagRegex.exec(content)) !== null) {
242
+ if (!/@unauthenticated|@public/i.test(ttm[1])) {
243
+ hasUntaggedTest = true;
244
+ break;
245
+ }
246
+ }
247
+ if (hasUntaggedTest) {
248
+ findings.push({
249
+ pattern: "test-use-scope",
250
+ file: filePath,
251
+ line,
252
+ message: "Conflicting test.use({ storageState }) scope — may silently break test isolation",
253
+ severity: "medium",
254
+ });
255
+ }
256
+ }
257
+ }
258
+ return findings;
259
+ }
260
+ // ─── Report Helpers ───────────────────────────────────────────────────
261
+ export function buildReport(findings) {
262
+ const patternCounts = {};
263
+ for (const f of findings) {
264
+ patternCounts[f.pattern] = (patternCounts[f.pattern] || 0) + 1;
265
+ }
266
+ const totalPatterns = Object.keys(patternCounts).length;
267
+ return {
268
+ findings,
269
+ patternCounts,
270
+ summaryText: `${findings.length} finding(s) across ${totalPatterns} pattern(s)`,
271
+ };
272
+ }
273
+ function renderReport(report) {
274
+ if (report.findings.length === 0) {
275
+ console.log(" ✅ No flake patterns detected.\n");
276
+ return;
277
+ }
278
+ // Group findings by pattern
279
+ const grouped = {};
280
+ for (const f of report.findings) {
281
+ if (!grouped[f.pattern])
282
+ grouped[f.pattern] = [];
283
+ grouped[f.pattern].push(f);
284
+ }
285
+ for (const [pattern, patternFindings] of Object.entries(grouped)) {
286
+ console.log(`─── ${pattern} ───`);
287
+ for (const f of patternFindings) {
288
+ console.log(` ⚠ ${f.file}:${f.line}`);
289
+ console.log(` ${f.message}`);
290
+ }
291
+ console.log();
292
+ }
293
+ console.log(`Summary: ${report.summaryText}\n`);
294
+ }
295
+ export function computeGateExitCode(report, gate) {
296
+ const level = gate.toUpperCase();
297
+ if (level === "HIGH") {
298
+ return report.findings.some((f) => f.severity === "high") ? 1 : 0;
299
+ }
300
+ if (level === "MEDIUM") {
301
+ return report.findings.some((f) => f.severity === "high" || f.severity === "medium")
302
+ ? 1
303
+ : 0;
304
+ }
305
+ if (level === "ALL") {
306
+ return report.findings.length > 0 ? 1 : 0;
307
+ }
308
+ // Default to HIGH
309
+ return report.findings.some((f) => f.severity === "high") ? 1 : 0;
310
+ }
311
+ //# sourceMappingURL=flake.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flake.js","sourceRoot":"","sources":["../../src/commands/flake.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -97,6 +97,23 @@ program
97
97
  await audit();
98
98
  await checkForUpdate(pkg.version);
99
99
  });
100
+ program
101
+ .command("coverage [change-name]")
102
+ .description("Analyze spec–test coverage for OpenSpec changes")
103
+ .option("--json", "Output results as JSON")
104
+ .action(async (changeName, opts) => {
105
+ const { coverage } = await import("./commands/coverage.js");
106
+ await coverage(changeName, opts);
107
+ });
108
+ program
109
+ .command("flake [change-name]")
110
+ .description("Detect static flake patterns in Playwright test files")
111
+ .option("--json", "Output results as JSON")
112
+ .option("--gate <severity>", "Exit non-zero if findings meet severity (HIGH|MEDIUM|ALL)")
113
+ .action(async (changeName, opts) => {
114
+ const { flake } = await import("./commands/flake.js");
115
+ await flake(changeName, opts);
116
+ });
100
117
  program
101
118
  .command("explore")
102
119
  .description("Explore routes in parallel with Playwright")
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openspec-playwright",
3
- "version": "0.3.47",
3
+ "version": "0.3.48",
4
4
  "description": "OpenSpec + Playwright E2E verification setup tool for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,35 +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
- export interface VisionCheckOptions {
17
- screenshots: string;
18
- config?: string;
19
- parallel?: number;
20
- output?: string;
21
- dryRun?: boolean;
22
- severity?: string;
23
- json?: boolean;
24
- viewport?: string;
25
- url?: string;
26
- baseline?: boolean;
27
- diff?: boolean;
28
- report?: string;
29
- threshold?: number;
30
- noCache?: boolean;
31
- }
32
- /**
33
- * Main vision check command.
34
- */
35
- export declare function visionCheck(options: VisionCheckOptions): Promise<void>;