deflake 1.2.48 → 1.2.50

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 +18 -6
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -406,8 +406,8 @@ async function analyzeAndFix(artifacts, client, argv, capturedOutput = '', backu
406
406
  if (loc) {
407
407
  console.log(` ${C.GRAY}📍 Location:${C.RESET} ${path.basename(loc.path)}:${loc.line} ${C.GRAY}(from ${locSource})${C.RESET}`);
408
408
 
409
- // Dedup: skip if this source file was already fixed by a previous artifact
410
- const fileKey = loc.path;
409
+ // Dedup: skip if this EXACT file:line was already fixed by a previous artifact
410
+ const fileKey = `${loc.path}:${loc.line}`;
411
411
  if (fixedFiles.has(fileKey)) {
412
412
  console.log(` ${C.GREEN}⏭️ Already fixed by a previous artifact — skipping duplicate${C.RESET}`);
413
413
  console.log('');
@@ -464,9 +464,16 @@ async function analyzeAndFix(artifacts, client, argv, capturedOutput = '', backu
464
464
  if (p.new_line && p.action === 'REPLACE') {
465
465
  const validation = validateSelectorAgainstAxTree(p.new_line, content);
466
466
  if (!validation.valid) {
467
- allValid = false;
468
- rejections.push(`Line ${p.line}: "${p.new_line.trim()}" REJECTED: ${validation.reason}`);
469
- console.log(` ${C.YELLOW}🔍 Validation FAILED for line ${p.line}: ${validation.reason}${C.RESET}`);
467
+ // On last retry: allow getByRole/getByText through (dynamic elements not in initial AX tree)
468
+ const isLastRetry = retryIdx === MAX_VALIDATION_RETRIES - 1;
469
+ const isAccessibilitySelector = /getBy(Role|Text|Label|Placeholder)/.test(p.new_line);
470
+ if (isLastRetry && isAccessibilitySelector) {
471
+ console.log(` ${C.YELLOW}🔍 Validation SOFT-PASS for line ${p.line}: ${validation.reason} (last retry, allowing accessibility selector)${C.RESET}`);
472
+ } else {
473
+ allValid = false;
474
+ rejections.push(`Line ${p.line}: "${p.new_line.trim()}" → REJECTED: ${validation.reason}`);
475
+ console.log(` ${C.YELLOW}🔍 Validation FAILED for line ${p.line}: ${validation.reason}${C.RESET}`);
476
+ }
470
477
  } else {
471
478
  console.log(` ${C.GREEN}🔍 Validation OK for line ${p.line}: ${validation.reason}${C.RESET}`);
472
479
  }
@@ -529,7 +536,7 @@ async function analyzeAndFix(artifacts, client, argv, capturedOutput = '', backu
529
536
  console.log(` ${C.BRIGHT}💉 Applying patches...${C.RESET}`);
530
537
  if (await applyFix(res, fixLoc, backups)) {
531
538
  count++;
532
- fixedFiles.add(fixLoc.path); // Track: don't fix this file again
539
+ fixedFiles.add(`${fixLoc.path}:${fixLoc.line}`); // Track: don't fix this exact location again
533
540
  console.log(` ${C.GREEN}${C.BRIGHT}✅ Fix applied to ${path.basename(fixLoc.path)}:${fixLoc.line}${C.RESET}`);
534
541
  } else {
535
542
  console.log(` ${C.YELLOW}⚠️ Patches could not be applied (see details above)${C.RESET}`);
@@ -611,6 +618,11 @@ async function applyFix(res, loc, backups = new Map()) {
611
618
  console.log(` ${C.GRAY}⏭️ Skipped (already present): ${p.new_line.trim().substring(0, 60)}...${C.RESET}`);
612
619
  continue;
613
620
  }
621
+ // Safety: block constructor patterns (this.xxx =) from being inserted into spec/test files
622
+ if (/\.(spec|test)\.(ts|js)$/.test(loc.path) && /^\s*this\.\w+\s*=/.test(p.new_line)) {
623
+ console.log(` ${C.YELLOW}⏭️ Blocked: constructor assignment in spec file (${p.new_line.trim().substring(0, 50)})${C.RESET}`);
624
+ continue;
625
+ }
614
626
  if (p.action === 'INSERT_AFTER') {
615
627
  // SAFETY: Detect if we'd insert at class scope (outside any method)
616
628
  // Pattern: line is '}' (end of constructor/method) and next non-blank line starts a new method
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deflake",
3
- "version": "1.2.48",
3
+ "version": "1.2.50",
4
4
  "description": "AI-powered self-healing tool for Playwright, Cypress, and WebdriverIO tests.",
5
5
  "main": "client.js",
6
6
  "bin": {