sela-core 1.0.1 → 1.0.3

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/dist/cli/index.js CHANGED
@@ -58,7 +58,7 @@ const program = new commander_1.Command();
58
58
  program
59
59
  .name('sela')
60
60
  .description('Sela CLI — proactive DNA management for Fixwright')
61
- .version('1.0.1')
61
+ .version('1.0.3')
62
62
  .exitOverride(ErrorHandler_js_1.handleError)
63
63
  .configureOutput({ outputError: () => { } });
64
64
  // ── sela init ────────────────────────────────────────────────────────────────
@@ -1 +1 @@
1
- {"version":3,"file":"expectProxy.d.ts","sourceRoot":"","sources":["../../src/fixtures/expectProxy.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,OAAO,EAER,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AA2N5D;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,OAAO,kBAAkB,EAAE,IAAI,EACrC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EAAE,6CAA6C;AAClE,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,GAAG,IAAI,GAChD,CAAC,cAAc,EAAE,OAAO,KAAK,GAAG,CA2DlC"}
1
+ {"version":3,"file":"expectProxy.d.ts","sourceRoot":"","sources":["../../src/fixtures/expectProxy.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,OAAO,EAER,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAgO5D;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,OAAO,kBAAkB,EAAE,IAAI,EACrC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EAAE,6CAA6C;AAClE,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,GAAG,IAAI,GAChD,CAAC,cAAc,EAAE,OAAO,KAAK,GAAG,CAiElC"}
@@ -29,6 +29,11 @@ function isRealLocator(value) {
29
29
  return false;
30
30
  if (typeof value !== "object")
31
31
  return false;
32
+ // Fixwright locator proxies expose `_fixwrightSelector`. The proxy forwards
33
+ // `_frame` via Reflect.get so `hasFrame` would lie — explicitly reject them
34
+ // here. Callers should unwrap via `resolveProxy` first.
35
+ if (value._fixwrightSelector !== undefined)
36
+ return false;
32
37
  const hasFrame = value._frame !== undefined ||
33
38
  value._impl?._frame !== undefined;
34
39
  const isFrameLocator = value._frameSelector !== undefined ||
@@ -206,6 +211,11 @@ resolveProxy) {
206
211
  resolved = unwrapped;
207
212
  }
208
213
  const base = (0, test_1.expect)(resolved);
214
+ // Defensive: if for any reason `base` is not an object, return it as-is
215
+ // rather than crashing inside `new Proxy(...)`.
216
+ if (base === null || typeof base !== "object") {
217
+ return base;
218
+ }
209
219
  // Step 2 — only wrap matchers for genuine page-level Locator objects.
210
220
  if (!isRealLocator(resolved)) {
211
221
  return base;
@@ -1,4 +1,6 @@
1
+ import { Locator } from "@playwright/test";
1
2
  import { createHealingExpect } from "./expectProxy";
3
+ export declare function resolveFixwrightProxy(value: unknown): Locator | null;
2
4
  export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & {
3
5
  expect: ReturnType<typeof createHealingExpect>;
4
6
  }, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fixtures/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAk2BpD,eAAO,MAAM,IAAI;YACP,UAAU,CAAC,OAAO,mBAAmB,CAAC;wGA+F9C,CAAC;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fixtures/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,OAAO,EAER,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAWpD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAIpE;AA02BD,eAAO,MAAM,IAAI;YACP,UAAU,CAAC,OAAO,mBAAmB,CAAC;wGA+F9C,CAAC;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.createHealingExpect = exports.test = void 0;
37
+ exports.resolveFixwrightProxy = resolveFixwrightProxy;
37
38
  const test_1 = require("@playwright/test");
38
39
  const StackUtils_1 = require("../utils/StackUtils");
39
40
  const HealingRegistry_1 = require("../engine/HealingRegistry");
@@ -43,6 +44,15 @@ const fs = __importStar(require("fs"));
43
44
  const path = __importStar(require("path"));
44
45
  const registry = HealingRegistry_1.HealingRegistry.getInstance();
45
46
  const proxyToActiveLocator = new WeakMap();
47
+ // Module-level resolver — moduleExpect.ts uses this to unwrap a Fixwright
48
+ // locator proxy back to its live underlying Playwright Locator without
49
+ // needing access to the WeakMap directly.
50
+ function resolveFixwrightProxy(value) {
51
+ if (!value || typeof value !== "object")
52
+ return null;
53
+ const getActive = proxyToActiveLocator.get(value);
54
+ return getActive ? getActive() : null;
55
+ }
46
56
  // ─── Action classification (identical to original) ────────────────
47
57
  const INTERCEPTED_ACTIONS = [
48
58
  "click",
@@ -461,6 +471,12 @@ function createFrameLocatorProxy(rawFrameLocator, frameSelector, rawPage, testTi
461
471
  // 3. Exposes _fixwrightUnsubscribe so the fixture can clean up.
462
472
  // ─────────────────────────────────────────────────────────────────
463
473
  function createLocatorProxy(rawLocator, selector, rawPage, testTitle, actionCounter, elementSelectorOnly) {
474
+ // Defensive: Proxy ctor throws "Cannot create proxy with a non-object as target"
475
+ // when downstream callers (e.g. chained traps) pass a non-Locator return value.
476
+ // Returning the raw value lets the caller see it unchanged instead of crashing.
477
+ if (rawLocator === null || rawLocator === undefined || typeof rawLocator !== "object") {
478
+ return rawLocator;
479
+ }
464
480
  // ── Resolve immediately (handles post-heal proxy creation) ────
465
481
  const initialResolved = registry.resolveSelector(selector);
466
482
  let currentFullSelector = initialResolved;
@@ -517,9 +533,13 @@ function createLocatorProxy(rawLocator, selector, rawPage, testTitle, actionCoun
517
533
  // ── getBy* ───────────────────────────────────────────────
518
534
  if (prop in GET_BY_METHODS) {
519
535
  return (...args) => {
536
+ const nextLocator = activeLocator[prop](...args);
537
+ if (nextLocator === null || nextLocator === undefined || typeof nextLocator !== "object") {
538
+ return nextLocator;
539
+ }
520
540
  const semanticSelector = GET_BY_METHODS[prop](args);
521
541
  const childFullSelector = `${currentFullSelector} >> ${semanticSelector}`;
522
- return createLocatorProxy(activeLocator[prop](...args), childFullSelector, rawPage, testTitle, actionCounter, semanticSelector);
542
+ return createLocatorProxy(nextLocator, childFullSelector, rawPage, testTitle, actionCounter, semanticSelector);
523
543
  };
524
544
  }
525
545
  // ── Chainable methods ────────────────────────────────────
@@ -527,6 +547,9 @@ function createLocatorProxy(rawLocator, selector, rawPage, testTitle, actionCoun
527
547
  if (chainables.includes(prop)) {
528
548
  return (...args) => {
529
549
  const nextLocator = activeLocator[prop](...args);
550
+ if (nextLocator === null || nextLocator === undefined || typeof nextLocator !== "object") {
551
+ return nextLocator;
552
+ }
530
553
  let nextFull = currentFullSelector;
531
554
  let nextElement = currentElementSelector;
532
555
  if (prop === "locator") {
@@ -1 +1 @@
1
- {"version":3,"file":"moduleExpect.d.ts","sourceRoot":"","sources":["../../src/fixtures/moduleExpect.ts"],"names":[],"mappings":"AAsCA,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,GAAG,CAO1C"}
1
+ {"version":3,"file":"moduleExpect.d.ts","sourceRoot":"","sources":["../../src/fixtures/moduleExpect.ts"],"names":[],"mappings":"AA8CA,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,GAAG,CAa1C"}
@@ -7,6 +7,7 @@ exports.expect = expect;
7
7
  const test_1 = require("@playwright/test");
8
8
  const singleton_js_1 = require("../engine/singleton.js");
9
9
  const expectProxy_js_1 = require("./expectProxy.js");
10
+ const index_js_1 = require("./index.js");
10
11
  function extractPage(value) {
11
12
  if (!value || typeof value !== 'object')
12
13
  return null;
@@ -27,12 +28,19 @@ function extractPage(value) {
27
28
  }
28
29
  function getCallerFile() {
29
30
  const lines = new Error().stack?.split('\n') ?? [];
30
- for (let i = 3; i < lines.length; i++) {
31
- if (/\.(spec|test)\.[jt]sx?/.test(lines[i])) {
32
- const m = lines[i].match(/\((.+?):\d+:\d+\)/);
33
- if (m)
34
- return m[1];
35
- }
31
+ // Match BOTH frame shapes V8 emits:
32
+ // " at fnName (D:\\path\\file.spec.ts:17:20)"
33
+ // " at D:\\path\\file.spec.ts:17:20"
34
+ // The path may include Windows drive letters (colon after C/D/...).
35
+ const FRAME_WITH_PARENS = /\(([^()]+?):\d+:\d+\)\s*$/;
36
+ const FRAME_BARE = /\s+at\s+(.+?):\d+:\d+\s*$/;
37
+ for (let i = 1; i < lines.length; i++) {
38
+ const line = lines[i];
39
+ if (!/\.(spec|test)\.[jt]sx?/.test(line))
40
+ continue;
41
+ const m = line.match(FRAME_WITH_PARENS) ?? line.match(FRAME_BARE);
42
+ if (m && m[1])
43
+ return m[1].trim();
36
44
  }
37
45
  return '';
38
46
  }
@@ -40,7 +48,7 @@ function expect(value) {
40
48
  const page = extractPage(value);
41
49
  if (page) {
42
50
  const filePath = getCallerFile();
43
- return (0, expectProxy_js_1.createHealingExpect)(singleton_js_1.sharedEngine, page, filePath, 0)(value);
51
+ return (0, expectProxy_js_1.createHealingExpect)(singleton_js_1.sharedEngine, page, filePath, 0, index_js_1.resolveFixwrightProxy)(value);
44
52
  }
45
53
  return (0, test_1.expect)(value);
46
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ASTSourceUpdater.d.ts","sourceRoot":"","sources":["../../src/services/ASTSourceUpdater.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAQ/C,OAAO,EAAE,cAAc,EAAgB,MAAM,mBAAmB,CAAC;AAOjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAMtD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kGAAkG;IAClG,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,cAAc,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAg5DD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAU;IACzB,QAAQ,CAAC,cAAc,iBAAwB;IAE/C,eAAe,IAAI,IAAI;;IAiBvB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAcjC;IAEH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CA8B9B;IAEH,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAuB/B;IAMH,MAAM,CACJ,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,eAAe,EAAE,EAC9B,mBAAmB,CAAC,EAAE,MAAM,EAC5B,aAAa,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EACpD,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,EACxC,iBAAiB,CAAC,EAAE,iBAAiB,EAAE,GACtC,eAAe;IA8PlB,OAAO,CAAC,kBAAkB;IAsM1B,OAAO,CAAC,uBAAuB;IA6F/B,OAAO,CAAC,qBAAqB;IAyF7B,OAAO,CAAC,YAAY;IAkDpB,OAAO,CAAC,qBAAqB;IA0G7B,OAAO,CAAC,4BAA4B;IAoRpC,OAAO,CAAC,yBAAyB;IAsGjC,OAAO,CAAC,uBAAuB;IA4E/B,OAAO,CAAC,4BAA4B;IA4EpC,OAAO,CAAC,qBAAqB;IA6B7B,OAAO,CAAC,oBAAoB;IAwB5B,OAAO,CAAC,gBAAgB;IAwBxB;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAUhC,OAAO,CAAC,mBAAmB;IAuC3B,OAAO,CAAC,kBAAkB;IA2B1B,OAAO,CAAC,kBAAkB;IAuB1B,OAAO,CAAC,2BAA2B;IAsCnC,OAAO,CAAC,yBAAyB;IAqCjC,OAAO,CAAC,yBAAyB;IA+CjC,OAAO,CAAC,qBAAqB;IAQ7B,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,0BAA0B;IAmBlC,OAAO,CAAC,sBAAsB;IA2B9B,OAAO,CAAC,2BAA2B;IAoCnC,OAAO,CAAC,oBAAoB;IA2B5B,OAAO,CAAC,YAAY;IAUpB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAa3C,OAAO,CAAC,gBAAgB;IAkExB,OAAO,CAAC,mBAAmB;IAiF3B,OAAO,CAAC,uBAAuB;IAiF/B,OAAO,CAAC,wBAAwB;IAkFhC,OAAO,CAAC,mBAAmB;IA8C3B,OAAO,CAAC,uBAAuB;IAoF/B,OAAO,CAAC,kBAAkB;IAwB1B,OAAO,CAAC,kBAAkB;CAgB3B"}
1
+ {"version":3,"file":"ASTSourceUpdater.d.ts","sourceRoot":"","sources":["../../src/services/ASTSourceUpdater.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAQ/C,OAAO,EAAE,cAAc,EAAgB,MAAM,mBAAmB,CAAC;AAOjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAMtD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kGAAkG;IAClG,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,cAAc,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAg5DD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAU;IACzB,QAAQ,CAAC,cAAc,iBAAwB;IAE/C,eAAe,IAAI,IAAI;;IAiBvB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAcjC;IAEH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CA8B9B;IAEH,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAuB/B;IAMH,MAAM,CACJ,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,eAAe,EAAE,EAC9B,mBAAmB,CAAC,EAAE,MAAM,EAC5B,aAAa,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EACpD,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,EACxC,iBAAiB,CAAC,EAAE,iBAAiB,EAAE,GACtC,eAAe;IA8PlB,OAAO,CAAC,kBAAkB;IAsM1B,OAAO,CAAC,uBAAuB;IA6F/B,OAAO,CAAC,qBAAqB;IAyF7B,OAAO,CAAC,YAAY;IAkDpB,OAAO,CAAC,qBAAqB;IA0G7B,OAAO,CAAC,4BAA4B;IAoRpC,OAAO,CAAC,yBAAyB;IAsGjC,OAAO,CAAC,uBAAuB;IA4E/B,OAAO,CAAC,4BAA4B;IA4EpC,OAAO,CAAC,qBAAqB;IA6B7B,OAAO,CAAC,oBAAoB;IAwB5B,OAAO,CAAC,gBAAgB;IAwBxB;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAUhC,OAAO,CAAC,mBAAmB;IAuC3B,OAAO,CAAC,kBAAkB;IA2B1B,OAAO,CAAC,kBAAkB;IAuB1B,OAAO,CAAC,2BAA2B;IAsCnC,OAAO,CAAC,yBAAyB;IAqCjC,OAAO,CAAC,yBAAyB;IA+CjC,OAAO,CAAC,qBAAqB;IAQ7B,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,0BAA0B;IAmBlC,OAAO,CAAC,sBAAsB;IA2B9B,OAAO,CAAC,2BAA2B;IAoCnC,OAAO,CAAC,oBAAoB;IA2B5B,OAAO,CAAC,YAAY;IAUpB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAkB3C,OAAO,CAAC,gBAAgB;IAkExB,OAAO,CAAC,mBAAmB;IAiF3B,OAAO,CAAC,uBAAuB;IAiF/B,OAAO,CAAC,wBAAwB;IAkFhC,OAAO,CAAC,mBAAmB;IA8C3B,OAAO,CAAC,uBAAuB;IAoF/B,OAAO,CAAC,kBAAkB;IAwB1B,OAAO,CAAC,kBAAkB;CAgB3B"}
@@ -2791,13 +2791,22 @@ class ASTSourceUpdater {
2791
2791
  return offset;
2792
2792
  }
2793
2793
  resolveFilePath(raw) {
2794
+ if (!raw || typeof raw !== "string")
2795
+ return null;
2794
2796
  let clean = raw
2795
2797
  .replace(/^.*?at\s+/, "")
2796
2798
  .replace(/:\d+:\d+.*$/, "")
2797
2799
  .trim();
2800
+ if (!clean)
2801
+ return null;
2798
2802
  if (!path.isAbsolute(clean))
2799
2803
  clean = path.resolve(process.cwd(), clean);
2800
- return fs.existsSync(clean) ? clean : null;
2804
+ if (!fs.existsSync(clean))
2805
+ return null;
2806
+ const stat = fs.statSync(clean);
2807
+ if (!stat.isFile())
2808
+ return null;
2809
+ return clean;
2801
2810
  }
2802
2811
  // ═══════════════════════════════════════════════════════════════════
2803
2812
  // T-10 / T-11: Semantic Dispatch Gate + handlers
@@ -1 +1 @@
1
- {"version":3,"file":"SourceUpdater.d.ts","sourceRoot":"","sources":["../../src/services/SourceUpdater.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAMtD,UAAU,YAAY;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,cAAc,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AA0YD,qBAAa,aAAa;IAMxB,MAAM,CAAC,MAAM,CACX,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,EACpB,mBAAmB,CAAC,EAAE,MAAM,EAC5B,UAAU,CAAC,EAAE,eAAe,EAAE,EAC9B,aAAa,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EACpD,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,EACxC,iBAAiB,CAAC,EAAE,iBAAiB,EAAE,EACvC,cAAc,CAAC,EAAE,SAAS,GAAG,aAAa,GAAG,QAAQ,EACrD,UAAU,CAAC,EAAE,OAAO,GACnB,YAAY;IAoDf,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAwC/B,OAAO,CAAC,MAAM,CAAC,WAAW;IAwS1B,OAAO,CAAC,MAAM,CAAC,2BAA2B;IA8E1C,OAAO,CAAC,MAAM,CAAC,wBAAwB;IA8EvC,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAoErC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAsBjC,OAAO,CAAC,MAAM,CAAC,qBAAqB;IA6DpC,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAuCpC,OAAO,CAAC,MAAM,CAAC,wBAAwB;IA6CvC,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAqCrC,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAqGrC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IA0BjC,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAatC,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IASlD,MAAM,CAAC,cAAc,CACnB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,YAAY;IA0Cf,0FAA0F;IAC1F,MAAM,CAAC,eAAe,IAAI,IAAI;CAG/B"}
1
+ {"version":3,"file":"SourceUpdater.d.ts","sourceRoot":"","sources":["../../src/services/SourceUpdater.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAMtD,UAAU,YAAY;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,cAAc,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AA0YD,qBAAa,aAAa;IAMxB,MAAM,CAAC,MAAM,CACX,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,EACpB,mBAAmB,CAAC,EAAE,MAAM,EAC5B,UAAU,CAAC,EAAE,eAAe,EAAE,EAC9B,aAAa,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EACpD,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,EACxC,iBAAiB,CAAC,EAAE,iBAAiB,EAAE,EACvC,cAAc,CAAC,EAAE,SAAS,GAAG,aAAa,GAAG,QAAQ,EACrD,UAAU,CAAC,EAAE,OAAO,GACnB,YAAY;IAoDf,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAwC/B,OAAO,CAAC,MAAM,CAAC,WAAW;IAwS1B,OAAO,CAAC,MAAM,CAAC,2BAA2B;IA8E1C,OAAO,CAAC,MAAM,CAAC,wBAAwB;IA8EvC,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAoErC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAsBjC,OAAO,CAAC,MAAM,CAAC,qBAAqB;IA6DpC,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAuCpC,OAAO,CAAC,MAAM,CAAC,wBAAwB;IA6CvC,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAqCrC,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAqGrC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IA0BjC,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAatC,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAgBlD,MAAM,CAAC,cAAc,CACnB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,YAAY;IA0Cf,0FAA0F;IAC1F,MAAM,CAAC,eAAe,IAAI,IAAI;CAG/B"}
@@ -971,13 +971,24 @@ class SourceUpdater {
971
971
  return domValueMatch?.[1] ?? null;
972
972
  }
973
973
  static resolveFilePath(raw) {
974
+ if (!raw || typeof raw !== "string")
975
+ return null;
974
976
  let clean = raw
975
977
  .replace(/^.*?at\s+/, "")
976
978
  .replace(/:\d+:\d+.*$/, "")
977
979
  .trim();
980
+ if (!clean)
981
+ return null;
978
982
  if (!path.isAbsolute(clean))
979
983
  clean = path.resolve(process.cwd(), clean);
980
- return fs.existsSync(clean) ? clean : null;
984
+ if (!fs.existsSync(clean))
985
+ return null;
986
+ // Reject directories: fs.readFileSync on a dir throws EISDIR. This guards
987
+ // against ctx.filePath being empty → path.resolve(cwd, '') → cwd.
988
+ const stat = fs.statSync(clean);
989
+ if (!stat.isFile())
990
+ return null;
991
+ return clean;
981
992
  }
982
993
  static updateArgument(caller, action, oldArgument, newArgument) {
983
994
  const filePath = SourceUpdater.resolveFilePath(caller.filePath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sela-core",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "AI self-healing Playwright wrapper — drop-in replacement for @playwright/test",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",