From 4d30598e6b971c2882438a683639a7ce3d177990 Mon Sep 17 00:00:00 2001 From: luna Date: Tue, 21 Jul 2026 18:00:35 +0000 Subject: [PATCH] Add repository scan integration tests --- tests/repo-counter.test.js | 125 +++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 tests/repo-counter.test.js diff --git a/tests/repo-counter.test.js b/tests/repo-counter.test.js new file mode 100644 index 0000000..f2c967a --- /dev/null +++ b/tests/repo-counter.test.js @@ -0,0 +1,125 @@ +import assert from "node:assert/strict"; +import { mkdir, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises"; +import os from "node:os"; +import path from "node:path"; +import test from "node:test"; + +import { KeyManager } from "../dist/services/key-manager.js"; +import { RepoCounterService } from "../dist/services/repo-counter.js"; + +async function createHarness(options = {}) { + const root = await mkdtemp(path.join(os.tmpdir(), "loc-via-git-test-")); + const fixture = path.join(root, "fixture"); + const bin = path.join(root, "bin"); + const cloneLog = path.join(root, "clone-log"); + await mkdir(fixture, { recursive: true }); + await mkdir(bin); + await writeFile(path.join(bin, "git"), `#!/usr/bin/env node +import { appendFileSync, cpSync } from "node:fs"; +const args = process.argv.slice(2); +const command = args.includes("clone") ? "clone" : args.includes("rev-parse") ? "rev-parse" : "other"; +if (command === "clone") { + appendFileSync(process.env.LOC_TEST_CLONE_LOG, "clone\\n"); + if (process.env.LOC_TEST_HANG === "1") setInterval(() => {}, 1000); + cpSync(process.env.LOC_TEST_FIXTURE, args.at(-1), { recursive: true }); +} else if (command === "rev-parse") { + process.stdout.write("fixture-commit\\n"); +} +`, { mode: 0o755 }); + + const config = { + allowedGitHosts: ["example.test"], + apiKey: "", + cacheSweepIntervalMs: 60_000, + cacheTtlMs: 60_000, + cloneTimeoutMs: 100, + defaultSshKeyName: "", + generateSshKeyIfMissing: false, + maxConcurrentScans: 2, + maxFilesPerScan: 100, + maxFileSizeBytes: 1024 * 1024, + maxScanBytes: 1024 * 1024, + port: 3000, + rateLimitMax: 30, + rateLimitWindowMs: 60_000, + sshKeysDir: path.join(root, "keys"), + tempRoot: path.join(root, "tmp"), + trustProxy: false, + ...options + }; + const originalPath = process.env.PATH; + process.env.PATH = `${bin}:${originalPath}`; + process.env.LOC_TEST_FIXTURE = fixture; + process.env.LOC_TEST_CLONE_LOG = cloneLog; + const keyManager = new KeyManager(config); + const service = new RepoCounterService(config, keyManager); + await keyManager.initialize(); + await service.initialize(); + + return { + cloneLog, + config, + fixture, + root, + service, + async cleanup() { + process.env.PATH = originalPath; + delete process.env.LOC_TEST_FIXTURE; + delete process.env.LOC_TEST_CLONE_LOG; + delete process.env.LOC_TEST_HANG; + await rm(root, { recursive: true, force: true }); + } + }; +} + +test("scans fixture repositories, caches duplicate work, and cleans clone directories", async () => { + const harness = await createHarness(); + try { + await writeFile(path.join(harness.fixture, "main.ts"), "const value = 1;\n\nexport { value };\n"); + await mkdir(path.join(harness.fixture, "dist")); + await writeFile(path.join(harness.fixture, "dist", "bundle.min.js"), "ignored\n"); + + const request = { repo: "https://example.test/demo.git", ref: null, sshKey: null }; + const [first, second] = await Promise.all([harness.service.count(request), harness.service.count(request)]); + const third = await harness.service.count(request); + + assert.equal(first.commit, "fixture-commit"); + assert.equal(second.lineCount, 2); + assert.equal(third.cached, true); + assert.equal((await readFile(harness.cloneLog, "utf8")).trim().split("\n").length, 1); + assert.deepEqual(await readdir(harness.config.tempRoot), []); + } finally { + await harness.cleanup(); + } +}); + +test("rejects oversized files and still removes the temporary clone", async () => { + const harness = await createHarness({ maxFileSizeBytes: 10 }); + try { + await writeFile(path.join(harness.fixture, "large.ts"), "export const value = 123;\n"); + await assert.rejects( + harness.service.count({ repo: "https://example.test/demo.git", ref: null, sshKey: null }), + { statusCode: 413 } + ); + assert.deepEqual(await readdir(harness.config.tempRoot), []); + } finally { + await harness.cleanup(); + } +}); + +test("times out stalled clones and rejects unsupported repository URLs", async () => { + const harness = await createHarness({ cloneTimeoutMs: 50 }); + try { + process.env.LOC_TEST_HANG = "1"; + await assert.rejects( + harness.service.count({ repo: "https://example.test/demo.git", ref: null, sshKey: null }), + { statusCode: 504 } + ); + await assert.rejects( + harness.service.count({ repo: "file:///private/repo", ref: null, sshKey: null }), + { statusCode: 400 } + ); + } finally { + await harness.cleanup(); + } +});