deflake 1.2.33 → 1.2.34

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.
Files changed (2) hide show
  1. package/cli.js +25 -26
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -294,36 +294,35 @@ function extractLoc(text) {
294
294
  if (!text) return null;
295
295
 
296
296
  // === MULTI-FRAMEWORK LOCATION EXTRACTION ===
297
- // Supports: Playwright, Cypress, WebdriverIO, Jest, Mocha
297
+ // Returns the LAST match (closest to the Error Context anchor)
298
+ // to avoid picking up stack traces from previous error blocks.
298
299
 
299
- // Strategy 1: Absolute path inside parentheses (most precise)
300
- // Format: at FunctionName (/absolute/path/file.ts:75:35)
301
- let m = text.match(/\(([^()]*?[\\/][^()]+\.(?:ts|js|tsx|jsx|mjs|cjs)):(\d+)(?::(\d+))?\)/);
302
- if (m) return { path: path.resolve(m[1]), line: parseInt(m[2]) };
303
-
304
- // Strategy 2: Absolute path after "at" keyword (no parens)
305
- // Format: at /absolute/path/file.ts:75:35
306
- m = text.match(/at\s+(\/[^\s]+\.(?:ts|js|tsx|jsx)):(\d+)(?::(\d+))?/);
307
- if (m) return { path: path.resolve(m[1]), line: parseInt(m[2]) };
308
-
309
- // Strategy 3: Relative path after "at" keyword
310
- // Format: at ../pages/file.ts:75
311
- m = text.match(/at\s+(\.\.?\/[^\s]+\.(?:ts|js|tsx|jsx)):(\d+)(?::(\d+))?/);
312
- if (m) return { path: path.resolve(m[1]), line: parseInt(m[2]) };
300
+ const patterns = [
301
+ // Strategy 1: Absolute path in parens — at Func (/path/file.ts:75:35)
302
+ /\(([^()]*?[\\/][^()]+\.(?:ts|js|tsx|jsx|mjs|cjs)):(\d+)(?::(\d+))?\)/g,
303
+ // Strategy 2: Absolute path — at /path/file.ts:75:35
304
+ /at\s+(\/[^\s]+\.(?:ts|js|tsx|jsx)):(\d+)(?::(\d+))?/g,
305
+ // Strategy 3: Relative path at ../pages/file.ts:75
306
+ /at\s+(\.\.?\/[^\s]+\.(?:ts|js|tsx|jsx)):(\d+)(?::(\d+))?/g,
307
+ ];
313
308
 
314
- // Strategy 4: Playwright "at file:line" in stack (single line match)
315
- m = text.match(/^\s+at\s+(.*?\.(?:ts|js)):(\d+)$/m);
316
- if (m) return { path: path.resolve(m[1]), line: parseInt(m[2]) };
317
-
318
- // Strategy 5: Cypress at Context.<anonymous> (path)
319
- m = text.match(/Context\.<anonymous>\s*\(([^)]+\.(?:ts|js|cy\.ts|cy\.js)):(\d+):(\d+)\)/);
320
- if (m) return { path: path.resolve(m[1]), line: parseInt(m[2]) };
309
+ let lastMatch = null;
310
+ for (const pattern of patterns) {
311
+ let m;
312
+ while ((m = pattern.exec(text)) !== null) {
313
+ lastMatch = { path: path.resolve(m[1]), line: parseInt(m[2]) };
314
+ }
315
+ if (lastMatch) return lastMatch;
316
+ }
321
317
 
322
- // Strategy 6: Generic — any path-like string with /dir/file.ts:line
323
- m = text.match(/((?:[\w@.-]+\/)+[\w.-]+\.(?:ts|js|tsx|jsx)):(\d+)/);
324
- if (m) return { path: path.resolve(m[1]), line: parseInt(m[2]) };
318
+ // Strategy 4: Generic — any path-like /dir/file.ts:line
319
+ const generic = /((?:[\w@.-]+\/)+[\w.-]+\.(?:ts|js|tsx|jsx)):(\d+)/g;
320
+ let m;
321
+ while ((m = generic.exec(text)) !== null) {
322
+ lastMatch = { path: path.resolve(m[1]), line: parseInt(m[2]) };
323
+ }
325
324
 
326
- return null;
325
+ return lastMatch;
327
326
  }
328
327
 
329
328
  async function runDoctor() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deflake",
3
- "version": "1.2.33",
3
+ "version": "1.2.34",
4
4
  "description": "AI-powered self-healing tool for Playwright, Cypress, and WebdriverIO tests.",
5
5
  "main": "client.js",
6
6
  "bin": {