Explorar o código

test: cover audited call and extraction regressions

Colby Mchenry hai 3 días
pai
achega
cabe319939

+ 6 - 1
__tests__/kernel-tsjs-parity.test.ts

@@ -115,7 +115,12 @@ function nested(holder) {
     const nested = result.nodes.find((n) => n.name === 'nested' && n.kind === 'function');
     expect(nested).toBeDefined();
     expect(result.unresolvedReferences.filter((r) => r.referenceKind === 'calls' && r.fromNodeId === nested!.id)
-      .map((r) => r.referenceName)).toEqual(['readKey', 'readKey', 'readKey', 'readKey']);
+      // Qualified sites are retained for effects; computed keys still make no
+      // receiver claim. All four calls inside arguments must also survive.
+      .map((r) => r.referenceName)).toEqual([
+        'holder.values.get', 'readKey', 'holder.values.get', 'readKey',
+        'readKey', 'holder.deep.values.get', 'readKey',
+      ]);
     expect(result.unresolvedReferences.some((r) => r.referenceName === 'values.get')).toBe(true);
   });
 

+ 8 - 3
__tests__/mcp-callers-truncation.test.ts

@@ -35,7 +35,8 @@ beforeAll(async () => {
       Array.from({ length: CALLERS }, (_, i) => `export function caller${i}(): number { return warm(${i}); }`).join('\n') +
       '\n'
   );
-  // `hot` shares its name with its file, so the answer groups per definition.
+  // Two real `hot` functions exercise per-definition truncation. A filename
+  // is not an overload of its exact-named function (#1809).
   fs.writeFileSync(path.join(tmpDir, 'src', 'hot.ts'), 'export function hot(n: number): number { return n; }\n');
   fs.writeFileSync(
     path.join(tmpDir, 'src', 'hot-callers.ts'),
@@ -43,6 +44,10 @@ beforeAll(async () => {
       Array.from({ length: CALLERS }, (_, i) => `export function hotCaller${i}(): number { return hot(${i}); }`).join('\n') +
       '\n'
   );
+  fs.writeFileSync(path.join(tmpDir, 'src', 'other-hot.ts'), 'export function hot(n: number): number { return n + 1; }\n');
+  fs.writeFileSync(path.join(tmpDir, 'src', 'other-hot-callers.ts'),
+    "import { hot } from './other-hot';\n" +
+    Array.from({ length: CALLERS }, (_, i) => `export function otherHotCaller${i}(): number { return hot(${i}); }`).join('\n') + '\n');
   fs.writeFileSync(
     path.join(tmpDir, 'src', 'fan.ts'),
     Array.from({ length: CALLERS }, (_, i) => `export function helper${i}(): number { return ${i}; }`).join('\n') +
@@ -76,8 +81,8 @@ describe('codegraph_callers truncation', () => {
 
   it('marks the cut inside each per-definition section too', async () => {
     const out = await text('codegraph_callers', { symbol: 'hot' });
-    expect(out).toContain('distinct definitions');
-    expect(out).toMatch(/- … \+\d+ more \(pass `limit` to widen\)/);
+    expect(out).toContain('2 distinct definitions');
+    expect(out.match(/- … \+\d+ more \(pass `limit` to widen\)/g)).toHaveLength(2);
     expect(await text('codegraph_callers', { symbol: 'hot', limit: 100 })).not.toContain('more (pass');
   });
 });

+ 3 - 5
__tests__/object-literal-methods.test.ts

@@ -9,11 +9,9 @@
  * MobX/handler maps) real nodes, so `codegraph_node`/`callers` on them resolve
  * instead of returning "not found" and forcing the agent to Read the store.
  *
- * Keyed purely on AST shape — no library names in the implementation — so any
- * same-shaped store is covered. Resolution then falls out of the existing
- * exact-name matcher: every call form (`const {foo}=useStore.getState(); foo()`,
- * `useStore.getState().foo()`, in-store `get().foo()`) reduces to a bare `foo`
- * call that resolves to the action node once it exists.
+ * Extraction is keyed on AST shape. The store-accessor resolver follows
+ * destructured bindings, `useStore.getState().foo()`, and in-store `get().foo()`
+ * to implementations within the store, excluding interface declarations.
  */
 import { describe, it, expect, beforeAll, afterEach } from 'vitest';
 import * as fs from 'fs';