aboutsummaryrefslogtreecommitdiffstats
path: root/cli/test/discover.test.ts
blob: 3e23aebb8b2475994acb227aad21e72ef822c3d9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import { afterAll, describe, expect, test } from "bun:test";
import { mkdirSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { discoverProjects, isProjectDir } from "../src/core/discover.ts";

// Disk-backed scratch: /tmp is tmpfs on the dev box, and these are tiny, but
// the habit matters.
const root = mkdtempSync(join(tmpdir(), "sl0ppi-discover-"));
afterAll(() => rmSync(root, { recursive: true, force: true }));

function project(rel: string): void {
  mkdirSync(join(root, rel, ".sl0ppi"), { recursive: true });
  writeFileSync(join(root, rel, ".sl0ppi", "layout.kdl"), "pane\n");
}
function plainDir(rel: string): void {
  mkdirSync(join(root, rel), { recursive: true });
}

project("beta");
project("alpha");
plainDir("not-a-project");
plainDir(".hidden-dir");
mkdirSync(join(root, ".hidden-dir", ".sl0ppi"), { recursive: true });
project("group/nested"); // depth 2
writeFileSync(join(root, "a-file"), "");
symlinkSync(join(root, "alpha"), join(root, "linked"));
symlinkSync(join(root, "nowhere"), join(root, "broken-link"));

describe("discoverProjects", () => {
  test("finds directories carrying the .sl0ppi marker, alphabetically", () => {
    expect(discoverProjects(root)).toEqual(["alpha", "beta", "linked"]);
  });

  test("ignores directories without the marker", () => {
    expect(discoverProjects(root)).not.toContain("not-a-project");
  });

  test("ignores dotfiles even when they carry a marker", () => {
    expect(discoverProjects(root)).not.toContain(".hidden-dir");
  });

  test("is depth-1 by default", () => {
    expect(discoverProjects(root)).not.toContain("group/nested");
  });

  test("finds nested projects when asked", () => {
    expect(discoverProjects(root, { depth: 2 })).toContain("group/nested");
  });

  test("follows symlinked project dirs but survives broken ones", () => {
    const found = discoverProjects(root);
    expect(found).toContain("linked");
    expect(found).not.toContain("broken-link");
  });

  test("returns empty for a missing root instead of throwing", () => {
    expect(discoverProjects(join(root, "does-not-exist"))).toEqual([]);
  });
});

describe("isProjectDir", () => {
  test("requires the marker to be a directory", () => {
    expect(isProjectDir(join(root, "alpha"))).toBe(true);
    expect(isProjectDir(join(root, "not-a-project"))).toBe(false);
    expect(isProjectDir(join(root, "nope"))).toBe(false);
  });
});