import { afterEach, describe, expect, test } from "bun:test"; import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { findFileProjects, mergeProjectRootObservations } from "./discovery"; const tempDirs: string[] = []; async function createTempProject() { const dir = await mkdtemp(join(tmpdir(), "scribe-discovery-")); tempDirs.push(dir); return dir; } afterEach(async () => { await Promise.all( tempDirs.splice(0).map((dir) => rm(dir, { recursive: true, force: true })), ); }); describe("findFileProjects", () => { test("includes git remote for manifest roots that are also git repos", async () => { const projectDir = await createTempProject(); await writeFile( join(projectDir, "package.json"), JSON.stringify({ name: "scribe" }), ); await mkdir(join(projectDir, ".git"), { recursive: true }); await writeFile( join(projectDir, ".git", "config"), [ '[remote "origin"]', "\turl = git@github.com:b-open-io/scribe.git", "", ].join("\n"), ); const [project] = await findFileProjects(projectDir); expect(project).toMatchObject({ path: projectDir, detectedName: "scribe", gitRemote: "github.com/b-open-io/scribe", type: "npm", }); }); }); describe("mergeProjectRootObservations", () => { test("merges overlapping observations and keeps the normalized remote", () => { const path = "/Users/test/code/scribe"; const observations = mergeProjectRootObservations([ { path, detectedName: "scribe", gitRemote: null, scanRootId: "files-root", }, { path, detectedName: "scribe", gitRemote: "git@github.com:b-open-io/scribe.git", scanRootId: "git-root", }, ]); expect(observations).toEqual([ { path, detectedName: "scribe", gitRemote: "github.com/b-open-io/scribe", scanRootId: "git-root", }, ]); }); test("keeps a repeated remote-less folder as one remote-less root", () => { const path = "/Users/test/code/local-only"; const observations = mergeProjectRootObservations([ { path, detectedName: "local-only", gitRemote: undefined, scanRootId: "files-a", }, { path, detectedName: "local-only", gitRemote: undefined, scanRootId: "files-b", }, ]); expect(observations).toHaveLength(1); expect(observations[0]).toMatchObject({ path, detectedName: "local-only", scanRootId: "files-a", }); expect(observations[0].gitRemote).toBeUndefined(); }); });