deflake 1.2.29 → 1.2.31

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 +39 -12
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -115,6 +115,12 @@ async function analyzeAndFix(artifacts, client, argv, capturedOutput = '') {
115
115
  console.log(` ${C.YELLOW}⚠️ No failure artifacts detected. Run 'npx deflake doctor' to check permissions.${C.RESET}`);
116
116
  return 0;
117
117
  }
118
+
119
+ // Debug: verify captured output content
120
+ const hasErrorContext = capturedOutput.includes('Error Context:');
121
+ const errorContextCount = (capturedOutput.match(/Error Context:/g) || []).length;
122
+ console.log(`${C.GRAY}📊 Captured output: ${capturedOutput.length} chars, Error Context lines: ${errorContextCount}, has 'at ': ${capturedOutput.includes(' at ')}${C.RESET}`);
123
+
118
124
  console.log(`${C.BRIGHT}🔍 Analyzing ${artifacts.length} failure(s)...${C.RESET}\n`);
119
125
  let count = 0;
120
126
  for (let i = 0; i < artifacts.length; i++) {
@@ -256,24 +262,45 @@ async function applyFix(res, loc) {
256
262
  }
257
263
 
258
264
  function extractRelevantOutput(fullOutput, artifactName) {
259
- // Extract error sections from captured console output
260
- // Covers: Playwright, Cypress, WebdriverIO stack traces
265
+ // SMART: Use Playwright's "Error Context:" line to find the EXACT error block for this artifact.
266
+ // Each Playwright failure ends with: "Error Context: test-results/<artifact-name>/error-context.md"
267
+ // We find that line, then walk backwards to capture the full error + stack trace.
268
+
261
269
  const lines = fullOutput.split('\n');
262
- let relevant = [];
263
- let capturing = false;
264
270
 
265
- for (const line of lines) {
266
- if (line.includes('Error:') || line.includes('at ') || line.includes('Failing:')) {
267
- capturing = true;
271
+ // Find the Error Context line that matches this artifact
272
+ let anchorIdx = -1;
273
+ for (let i = 0; i < lines.length; i++) {
274
+ if (lines[i].includes('Error Context:') && lines[i].includes(artifactName)) {
275
+ anchorIdx = i;
276
+ break;
268
277
  }
269
- if (capturing) {
270
- relevant.push(line);
271
- if (line.includes('Error Context:') || (relevant.length > 30 && line.trim() === '')) {
272
- capturing = false;
278
+ }
279
+
280
+ if (anchorIdx === -1) {
281
+ // Fallback: try partial match on artifact name parts
282
+ const nameParts = artifactName.split('-').filter(p => p.length > 3);
283
+ for (let i = 0; i < lines.length; i++) {
284
+ if (lines[i].includes('Error Context:') && nameParts.some(part => lines[i].includes(part))) {
285
+ anchorIdx = i;
286
+ break;
273
287
  }
274
288
  }
275
289
  }
276
- return relevant.join('\n');
290
+
291
+ if (anchorIdx === -1) return '';
292
+
293
+ // Walk backwards from anchor to find the start of this error block
294
+ // Error blocks in Playwright start with "N) [chromium] › tests/..."
295
+ let startIdx = anchorIdx;
296
+ for (let i = anchorIdx; i >= 0; i--) {
297
+ if (lines[i].match(/^\s*\d+\)\s+\[/)) {
298
+ startIdx = i;
299
+ break;
300
+ }
301
+ }
302
+
303
+ return lines.slice(startIdx, anchorIdx + 1).join('\n');
277
304
  }
278
305
 
279
306
  function extractLoc(text) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deflake",
3
- "version": "1.2.29",
3
+ "version": "1.2.31",
4
4
  "description": "AI-powered self-healing tool for Playwright, Cypress, and WebdriverIO tests.",
5
5
  "main": "client.js",
6
6
  "bin": {