Files
socraticode/tests/unit/graph-discovery.test.ts
T
Matteo Di Mattia 8be929a1c2 test(graph): add Lua extractor + whitelist-discovery tests
Address maintainer review on PR #67.

- Add a dedicated `describe("Lua")` block locking in qualified
  `Table.method` / `T:m()` names, `local function`, both
  `T.f = function() … end` and `local f = function() … end` assignment
  forms, call attribution to the enclosing function, top-level calls
  falling back to `<module>`, and dotted-callee resolution.
- Move the former "handles Lua via regex fallback" test out of the
  regex-fallback block (Lua now routes to extractFromLua) and give it
  real assertions; drop "Lua" from that block's title.
- Add a whitelist `.gitignore` regression test (`/*` then `!/src/`)
  asserting files under the re-included dir are discovered; export
  getGraphableFiles so the test can exercise discovery directly.
- Match the dynamic-grammar style for the Lua parse call
  (`parse("lua" as unknown as Lang, source)`).
2026-06-09 19:58:54 +02:00

46 lines
1.7 KiB
TypeScript

// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Giancarlo Erra - Altaire Limited
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import { ensureDynamicLanguages, getGraphableFiles } from "../../src/services/code-graph.js";
// Regression for the whitelist .gitignore discovery fix: a `/*` then `!/src/`
// pattern ignores everything at the root but re-includes `src/`. The old walk
// passed `src` (no trailing slash) to shouldIgnore, which `/*` matched, so the
// walk bailed and produced an empty graph. Passing `src/` lets it descend and
// the files under the re-included directory are actually picked up.
describe("getGraphableFiles — whitelist .gitignore", () => {
let root: string;
beforeAll(() => {
ensureDynamicLanguages();
root = fs.mkdtempSync(path.join(os.tmpdir(), "socraticode-discovery-"));
fs.mkdirSync(path.join(root, "src"), { recursive: true });
fs.writeFileSync(path.join(root, ".gitignore"), "/*\n!/src/\n");
fs.writeFileSync(
path.join(root, "src", "mod.lua"),
"local function f()\n return 1\nend\nreturn f\n",
);
// A root-level file the `/*` pattern should keep ignored.
fs.writeFileSync(path.join(root, "ignored.lua"), "return 1\n");
});
afterAll(() => {
try {
fs.rmSync(root, { recursive: true, force: true });
} catch {
// ignore cleanup errors
}
});
it("descends into re-included src/ and discovers its files", async () => {
const files = await getGraphableFiles(root);
expect(files).toContain("src/mod.lua");
// The `/*` pattern still ignores top-level entries that are not re-included.
expect(files).not.toContain("ignored.lua");
});
});