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.
package/README.md CHANGED
@@ -47,6 +47,8 @@ openspec-pw init # Initialize integration (one-time setup; add --seed t
47
47
  openspec-pw update # Update CLI and commands to latest version
48
48
  openspec-pw doctor # Check prerequisites + app server diagnostics
49
49
  openspec-pw audit # Audit tests for orphaned specs and issues
50
+ openspec-pw coverage # Analyze spec–test coverage for changes
51
+ openspec-pw flake # Detect static flake patterns in test files
50
52
  openspec-pw migrate # Migrate old test files to new structure
51
53
  openspec-pw explore # Explore routes in parallel with Playwright
52
54
  openspec-pw run <name> # Execute E2E tests for a change
@@ -206,6 +208,7 @@ CLI (openspec-pw)
206
208
  ├── run → Executes E2E tests with server lifecycle
207
209
  ├── migrate → Migrates old test files to new structure
208
210
  ├── audit → Audits tests for orphaned specs and issues
211
+ ├── flake → Detects static flake patterns in test files
209
212
  ├── doctor → Checks prerequisites
210
213
  ├── explore → Explores routes in parallel with Playwright
211
214
  └── uninstall → Removes integration from the project
@@ -167,9 +167,11 @@ async function getChangeNames(projectRoot) {
167
167
  timeout: TIMEOUT.OPENSPEC_LIST,
168
168
  });
169
169
  const data = JSON.parse(result);
170
- return Array.isArray(data)
171
- ? data.map((c) => c.name)
172
- : Object.keys(data);
170
+ if (Array.isArray(data))
171
+ return data.map((c) => c.name);
172
+ if (data.changes && Array.isArray(data.changes))
173
+ return data.changes.map((c) => c.name);
174
+ return Object.keys(data);
173
175
  }
174
176
  catch {
175
177
  return [];
@@ -1 +1 @@
1
- {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ interface CoverageChange {
2
+ name: string;
3
+ testCount: number;
4
+ specScenarioCount: number;
5
+ matchedScenarioCount: number;
6
+ coveragePct: number;
7
+ uncoveredScenarios: string[];
8
+ coveredRoutes: string[];
9
+ uncoveredRoutes: string[];
10
+ }
11
+ interface CoverageReport {
12
+ changes: CoverageChange[];
13
+ overallTestCount: number;
14
+ overallScenarioCount: number;
15
+ overallMatchedCount: number;
16
+ overallCoveragePct: number;
17
+ orphanedTests: string[];
18
+ recommendations: string[];
19
+ }
20
+ interface Scenario {
21
+ name: string;
22
+ tags: string[];
23
+ routes: string[];
24
+ file: string;
25
+ }
26
+ interface TestCase {
27
+ name: string;
28
+ tags: string[];
29
+ routes: string[];
30
+ file: string;
31
+ }
32
+ export declare function coverage(changeName?: string, opts?: {
33
+ json?: boolean;
34
+ }): Promise<void>;
35
+ export declare function analyzeChange(name: string, projectRoot: string, testsDir: string, changesDir: string, _allTestFiles: string[]): CoverageChange;
36
+ export declare function computeOverall(changes: CoverageChange[], orphanedTests: string[], recommendations: string[]): CoverageReport;
37
+ export declare function parseScenarios(filePath: string): Scenario[];
38
+ export declare function parseTestCases(filePath: string): TestCase[];
39
+ export declare function extractKeywords(name: string): string[];
40
+ export declare function collectSpecFiles(dir: string, collected?: string[]): string[];
41
+ export {};
@@ -0,0 +1,368 @@
1
+ import { execFileSync } from "child_process";
2
+ import { existsSync, readFileSync, readdirSync } from "fs";
3
+ import { join } from "path";
4
+ import chalk from "chalk";
5
+ import { TIMEOUT, needsShell } from "../shared/index.js";
6
+ // ─── Main Entry Point ─────────────────────────────────────────────────
7
+ export async function coverage(changeName, opts) {
8
+ const projectRoot = process.cwd();
9
+ const testsDir = join(projectRoot, "tests", "playwright");
10
+ const changesDir = join(projectRoot, "openspec", "changes");
11
+ if (!existsSync(testsDir)) {
12
+ console.log(chalk.yellow(" tests/playwright/ not found. Run `openspec-pw init` first.\n"));
13
+ return;
14
+ }
15
+ console.log(chalk.blue("\n📊 OpenSpec Playwright: Coverage Analysis\n"));
16
+ // 1. Get all OpenSpec change names
17
+ const changeNames = await getChangeNames(projectRoot);
18
+ if (changeNames.length === 0) {
19
+ console.log(chalk.yellow(" No OpenSpec changes found. Run `openspec init` first.\n"));
20
+ return;
21
+ }
22
+ // Filter to single change if requested
23
+ const targetChanges = changeName
24
+ ? changeNames.filter((n) => n === changeName)
25
+ : changeNames;
26
+ if (changeName && targetChanges.length === 0) {
27
+ console.log(chalk.yellow(` Change "${changeName}" not found.\n`));
28
+ return;
29
+ }
30
+ // 2. Collect test files
31
+ const testFiles = collectTestFiles(testsDir);
32
+ // 3. Analyze each change
33
+ const changes = [];
34
+ const orphanedTests = [];
35
+ const allRecommendations = [];
36
+ for (const name of targetChanges) {
37
+ const change = analyzeChange(name, projectRoot, testsDir, changesDir, testFiles);
38
+ changes.push(change);
39
+ if (change.coveragePct === 0 && change.specScenarioCount > 0) {
40
+ allRecommendations.push(`Add tests for "${name}" (${change.specScenarioCount} scenarios uncovered)`);
41
+ }
42
+ }
43
+ // 4. Detect orphaned tests (test file with no matching change)
44
+ for (const tf of testFiles) {
45
+ const rel = tf.replace(testsDir + "/", "");
46
+ const match = rel.match(/^changes\/([^/]+)\//);
47
+ if (match && !changeNames.includes(match[1])) {
48
+ orphanedTests.push(rel);
49
+ }
50
+ }
51
+ if (orphanedTests.length > 0) {
52
+ allRecommendations.push(`${orphanedTests.length} orphaned test(s) — no matching OpenSpec change`);
53
+ }
54
+ // 5. Compute overall stats
55
+ const overall = computeOverall(changes, orphanedTests, allRecommendations);
56
+ // 6. Render
57
+ if (opts?.json) {
58
+ console.log(JSON.stringify(overall, null, 2));
59
+ }
60
+ else {
61
+ renderReport(overall);
62
+ }
63
+ }
64
+ // ─── Analysis Functions ───────────────────────────────────────────────
65
+ export function analyzeChange(name, projectRoot, testsDir, changesDir, _allTestFiles) {
66
+ // Spec dir: openspec/changes/<name>/specs/
67
+ const specDir = join(changesDir, name, "specs");
68
+ // Test dir: tests/playwright/changes/<name>/
69
+ const changeTestDir = join(testsDir, "changes", name);
70
+ // Parse spec scenarios
71
+ const scenarios = [];
72
+ if (existsSync(specDir)) {
73
+ const specFiles = collectMarkdownFiles(specDir);
74
+ for (const sf of specFiles) {
75
+ scenarios.push(...parseScenarios(sf));
76
+ }
77
+ }
78
+ // Parse test cases
79
+ const tests = [];
80
+ if (existsSync(changeTestDir)) {
81
+ const files = collectSpecFiles(changeTestDir);
82
+ for (const tf of files) {
83
+ tests.push(...parseTestCases(tf));
84
+ }
85
+ }
86
+ // Route extraction
87
+ const specRoutes = extractRoutes(scenarios.map((s) => s.routes).flat());
88
+ const testRoutes = extractRoutes(tests.map((t) => t.routes).flat());
89
+ // L2 — Route match: spec routes covered by test routes
90
+ const coveredRoutes = specRoutes.filter((r) => testRoutes.some((tr) => tr === r || tr.startsWith(r)));
91
+ const uncoveredRoutes = specRoutes.filter((r) => !coveredRoutes.includes(r));
92
+ // L3 — Tag match
93
+ const testTags = new Set(tests.flatMap((t) => t.tags));
94
+ // L1+L3+L4+L5 — Scenario matching
95
+ let matchedCount = 0;
96
+ const uncoveredScenarios = [];
97
+ for (const sc of scenarios) {
98
+ // L3: tag match
99
+ const tagMatched = sc.tags.length > 0 && sc.tags.some((t) => testTags.has(t));
100
+ // L4: keyword match — extract key terms from scenario name
101
+ const scKeywords = extractKeywords(sc.name);
102
+ const keywordMatched = tests.some((t) => scKeywords.some((kw) => t.name.toLowerCase().includes(kw)));
103
+ // L5: name contains (or similar by overlap)
104
+ const nameMatched = tests.some((t) => t.name.toLowerCase().includes(sc.name.toLowerCase()) ||
105
+ sc.name.toLowerCase().includes(t.name.toLowerCase()));
106
+ if (tagMatched || keywordMatched || nameMatched) {
107
+ matchedCount++;
108
+ }
109
+ else {
110
+ uncoveredScenarios.push(sc.name);
111
+ }
112
+ }
113
+ const totalScenarios = scenarios.length || 1; // avoid div-by-zero
114
+ const pct = Math.round((matchedCount / totalScenarios) * 100);
115
+ return {
116
+ name,
117
+ testCount: tests.length,
118
+ specScenarioCount: scenarios.length,
119
+ matchedScenarioCount: matchedCount,
120
+ coveragePct: pct,
121
+ uncoveredScenarios,
122
+ coveredRoutes,
123
+ uncoveredRoutes,
124
+ };
125
+ }
126
+ export function computeOverall(changes, orphanedTests, recommendations) {
127
+ const totalScenarios = changes.reduce((s, c) => s + c.specScenarioCount, 0);
128
+ const totalMatched = changes.reduce((s, c) => s + c.matchedScenarioCount, 0);
129
+ const totalTests = changes.reduce((s, c) => s + c.testCount, 0);
130
+ return {
131
+ changes,
132
+ overallTestCount: totalTests,
133
+ overallScenarioCount: totalScenarios,
134
+ overallMatchedCount: totalMatched,
135
+ overallCoveragePct: totalScenarios > 0
136
+ ? Math.round((totalMatched / totalScenarios) * 100)
137
+ : 0,
138
+ orphanedTests,
139
+ recommendations,
140
+ };
141
+ }
142
+ // ─── Parsing Helpers ──────────────────────────────────────────────────
143
+ export function parseScenarios(filePath) {
144
+ const content = readFileSync(filePath, "utf-8");
145
+ const scenarios = [];
146
+ const lines = content.split("\n");
147
+ let currentScenario = null;
148
+ let descriptionLines = [];
149
+ for (const line of lines) {
150
+ const scenarioMatch = line.match(/^#### Scenario:\s*(.+)/);
151
+ if (scenarioMatch) {
152
+ if (currentScenario?.name) {
153
+ scenarios.push(buildScenario(currentScenario, descriptionLines));
154
+ }
155
+ // Capture inline tags, then strip from name
156
+ const rawName = scenarioMatch[1].trim();
157
+ const inlineTags = [...new Set((rawName.match(/@\w+/g) ?? []).map((t) => t.toLowerCase()))];
158
+ const cleanName = rawName.replace(/@\w+/g, "").replace(/\s{2,}/g, " ").trim();
159
+ currentScenario = { name: cleanName, tags: inlineTags, routes: [] };
160
+ descriptionLines = [];
161
+ continue;
162
+ }
163
+ if (currentScenario) {
164
+ descriptionLines.push(line);
165
+ }
166
+ }
167
+ if (currentScenario?.name) {
168
+ scenarios.push(buildScenario(currentScenario, descriptionLines));
169
+ }
170
+ return scenarios;
171
+ }
172
+ function buildScenario(sc, descLines) {
173
+ const fullText = descLines.join(" ");
174
+ // Merge inline tags (already parsed) with description tags
175
+ const descTags = (fullText.match(/@\w+/g) ?? []).map((t) => t.toLowerCase());
176
+ const tags = [...new Set([...(sc.tags ?? []), ...descTags])];
177
+ // Extract routes
178
+ const routes = extractRoutesFromText(fullText);
179
+ return {
180
+ name: sc.name ?? "",
181
+ tags,
182
+ routes,
183
+ file: "",
184
+ };
185
+ }
186
+ export function parseTestCases(filePath) {
187
+ const content = readFileSync(filePath, "utf-8");
188
+ const tests = [];
189
+ const lines = content.split("\n");
190
+ for (const line of lines) {
191
+ // Match test('name', ...) or test("name", ...) or test(`name`, ...)
192
+ const match = line.match(/test\(['"`](.+)['"`]/);
193
+ if (match) {
194
+ const name = match[1].trim();
195
+ // Extract @tags
196
+ const tagMatches = name.match(/@\w+/g);
197
+ const tags = tagMatches ? [...new Set(tagMatches.map((t) => t.toLowerCase()))] : [];
198
+ // Extract routes from the line
199
+ const routes = extractRoutesFromText(name);
200
+ tests.push({ name, tags, routes, file: filePath });
201
+ }
202
+ }
203
+ return tests;
204
+ }
205
+ function extractRoutesFromText(text) {
206
+ const routes = [];
207
+ // Match goto('/path') or page.goto('/path')
208
+ const gotoPattern = /(?:page\s*\.\s*)?goto\s*\(\s*['"`](\/[^'"`]*)['"`]/g;
209
+ let m;
210
+ while ((m = gotoPattern.exec(text)) !== null) {
211
+ routes.push(m[1]);
212
+ }
213
+ // Also match bare paths like /login, /dashboard used in comments/specs
214
+ const pathPattern = /\b(\/[a-z][a-z0-9_\-/]*)/gi;
215
+ while ((m = pathPattern.exec(text)) !== null) {
216
+ const p = m[1];
217
+ if (!p.includes("//") && !p.includes(".") && p.split("/").length <= 4) {
218
+ routes.push(p);
219
+ }
220
+ }
221
+ return [...new Set(routes)];
222
+ }
223
+ function extractRoutes(routeList) {
224
+ return [...new Set(routeList)];
225
+ }
226
+ export function extractKeywords(name) {
227
+ // Extract meaningful words (≥3 chars, not common stop words)
228
+ const stopWords = new Set([
229
+ "the", "and", "for", "with", "from", "that", "this", "when",
230
+ "then", "user", "page", "test", "should", "can", "not",
231
+ ]);
232
+ return name
233
+ .toLowerCase()
234
+ .split(/[\s\-_/]+/)
235
+ .filter((w) => w.length >= 3 && !stopWords.has(w));
236
+ }
237
+ // ─── File Collection ──────────────────────────────────────────────────
238
+ function collectTestFiles(dir, collected = []) {
239
+ return collectSpecFiles(dir, collected);
240
+ }
241
+ export function collectSpecFiles(dir, collected = []) {
242
+ if (!existsSync(dir))
243
+ return collected;
244
+ const entries = readdirSync(dir, { withFileTypes: true });
245
+ for (const entry of entries) {
246
+ const fullPath = join(dir, entry.name);
247
+ if (entry.isDirectory()) {
248
+ if (!entry.name.startsWith(".") &&
249
+ entry.name !== "node_modules" &&
250
+ entry.name !== "__snapshots__") {
251
+ collectSpecFiles(fullPath, collected);
252
+ }
253
+ }
254
+ else if (entry.name.endsWith(".spec.ts")) {
255
+ collected.push(fullPath);
256
+ }
257
+ }
258
+ return collected;
259
+ }
260
+ function collectMarkdownFiles(dir, collected = []) {
261
+ if (!existsSync(dir))
262
+ return collected;
263
+ const entries = readdirSync(dir, { withFileTypes: true });
264
+ for (const entry of entries) {
265
+ const fullPath = join(dir, entry.name);
266
+ if (entry.isDirectory()) {
267
+ if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
268
+ collectMarkdownFiles(fullPath, collected);
269
+ }
270
+ }
271
+ else if (entry.name.endsWith(".md") && entry.name !== "test-plan.md") {
272
+ collected.push(fullPath);
273
+ }
274
+ }
275
+ return collected;
276
+ }
277
+ async function getChangeNames(projectRoot) {
278
+ try {
279
+ const result = execFileSync("npx", ["openspec", "list", "--json"], {
280
+ shell: needsShell,
281
+ cwd: projectRoot,
282
+ encoding: "utf-8",
283
+ timeout: TIMEOUT.OPENSPEC_LIST,
284
+ });
285
+ const data = JSON.parse(result);
286
+ if (Array.isArray(data))
287
+ return data.map((c) => c.name);
288
+ if (data.changes && Array.isArray(data.changes))
289
+ return data.changes.map((c) => c.name);
290
+ return Object.keys(data);
291
+ }
292
+ catch {
293
+ return [];
294
+ }
295
+ }
296
+ // ─── Report Rendering ─────────────────────────────────────────────────
297
+ function renderReport(report) {
298
+ const { changes, overallCoveragePct, orphanedTests, recommendations } = report;
299
+ if (changes.length === 0) {
300
+ console.log(chalk.yellow(" No changes to analyze.\n"));
301
+ return;
302
+ }
303
+ // Summary table (manually aligned for terminal)
304
+ const header = `${chalk.bold("Change".padEnd(24))} ${chalk.bold("Tests")} ${chalk.bold("Spec")} ${chalk.bold("Cov")}`;
305
+ const sep = "─".repeat(24) + " ───── ───── ─────";
306
+ console.log(` ${header}`);
307
+ console.log(` ${chalk.gray(sep)}`);
308
+ for (const c of changes) {
309
+ const name = c.name.padEnd(24);
310
+ const tests = String(c.testCount).padStart(3);
311
+ const specs = String(c.specScenarioCount).padStart(4);
312
+ const pct = formatPct(c.coveragePct);
313
+ console.log(` ${name} ${tests} ${specs} ${pct}`);
314
+ }
315
+ console.log();
316
+ // Overall
317
+ const overallColor = overallCoveragePct >= 80 ? chalk.green : overallCoveragePct >= 50 ? chalk.yellow : chalk.red;
318
+ console.log(` Overall coverage: ${overallColor(`${overallCoveragePct}%`)} (${report.overallMatchedCount}/${report.overallScenarioCount} scenarios)`);
319
+ console.log(` Total test cases: ${chalk.cyan(String(report.overallTestCount))}`);
320
+ console.log();
321
+ // Uncovered scenarios
322
+ const uncovered = changes.flatMap((c) => c.uncoveredScenarios.map((s) => ({ change: c.name, scenario: s })));
323
+ if (uncovered.length > 0) {
324
+ console.log(chalk.yellow(` 📋 Uncovered scenarios (${uncovered.length}):`));
325
+ for (const u of uncovered) {
326
+ console.log(chalk.gray(` ${u.change} → ${u.scenario}`));
327
+ }
328
+ console.log();
329
+ }
330
+ // Uncovered routes
331
+ const uncoveredRoutes = changes.flatMap((c) => c.uncoveredRoutes.map((r) => ({ change: c.name, route: r })));
332
+ if (uncoveredRoutes.length > 0) {
333
+ console.log(chalk.yellow(` 🛣️ Uncovered routes (${uncoveredRoutes.length}):`));
334
+ for (const u of uncoveredRoutes) {
335
+ console.log(chalk.gray(` ${u.change} → ${u.route}`));
336
+ }
337
+ console.log();
338
+ }
339
+ // Orphaned tests
340
+ if (orphanedTests.length > 0) {
341
+ console.log(chalk.red(` ⚠ Orphaned tests (${orphanedTests.length}):`));
342
+ for (const ot of orphanedTests) {
343
+ console.log(chalk.gray(` ${ot}`));
344
+ }
345
+ console.log();
346
+ }
347
+ // Recommendations
348
+ if (recommendations.length > 0) {
349
+ console.log(chalk.blue(" 💡 Recommendations:"));
350
+ for (const r of recommendations) {
351
+ console.log(chalk.gray(` • ${r}`));
352
+ }
353
+ console.log();
354
+ }
355
+ // Footer
356
+ if (uncovered.length === 0 && orphanedTests.length === 0) {
357
+ console.log(chalk.green(" ✅ Full coverage — all scenarios matched.\n"));
358
+ }
359
+ }
360
+ function formatPct(pct) {
361
+ const s = `${pct}%`.padStart(4);
362
+ if (pct >= 80)
363
+ return chalk.green(s);
364
+ if (pct >= 50)
365
+ return chalk.yellow(s);
366
+ return chalk.red(s);
367
+ }
368
+ //# sourceMappingURL=coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../src/commands/coverage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export interface FlakeFinding {
2
+ pattern: string;
3
+ file: string;
4
+ line: number;
5
+ message: string;
6
+ severity: "high" | "medium";
7
+ }
8
+ export interface FlakeReport {
9
+ findings: FlakeFinding[];
10
+ patternCounts: Record<string, number>;
11
+ summaryText: string;
12
+ }
13
+ export declare function flake(changeName?: string, options?: {
14
+ json?: boolean;
15
+ gate?: string;
16
+ }): Promise<void>;
17
+ export declare function getConfigStorageState(projectRoot: string): boolean;
18
+ export declare function detectNetworkIdle(content: string, filePath: string): FlakeFinding[];
19
+ export declare function detectRouteAfterGoto(content: string, filePath: string): FlakeFinding[];
20
+ export declare function detectStorageLeakage(content: string, filePath: string, configHasStorageState: boolean): FlakeFinding[];
21
+ export declare function detectTestUseScope(content: string, filePath: string, configHasStorageState: boolean): FlakeFinding[];
22
+ export declare function buildReport(findings: FlakeFinding[]): FlakeReport;
23
+ export declare function computeGateExitCode(report: FlakeReport, gate: string): number;