entry-name.test.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import { describe, expect, test } from "bun:test"
  2. import { posix } from "path"
  3. import { configEntryNameFromPath } from "@/config/entry-name"
  4. // Use POSIX semantics so the test is deterministic regardless of host OS —
  5. // production code passes paths through `path.relative` on the runtime
  6. // platform, but the helper normalizes via `replaceAll("\\", "/")`, so the
  7. // regression assertion ("the helper returns the bare name") holds on either
  8. // platform as long as we feed it a relative path. Using `posix.relative`
  9. // keeps the intermediate values stable across CI runners.
  10. // The prefixes shipped by config/agent.ts after the relative-path refactor.
  11. const AGENT_PREFIXES = ["agent/", "agents/"]
  12. describe("configEntryNameFromPath", () => {
  13. test("strips an `agents/` prefix and returns the bare name", () => {
  14. expect(configEntryNameFromPath("agents/build.md", AGENT_PREFIXES)).toBe("build")
  15. })
  16. test("strips an `agent/` (singular) prefix", () => {
  17. expect(configEntryNameFromPath("agent/build.md", AGENT_PREFIXES)).toBe("build")
  18. })
  19. test("preserves nested subdirectories in the key", () => {
  20. expect(configEntryNameFromPath("agents/team/build.md", AGENT_PREFIXES)).toBe("team/build")
  21. })
  22. test("normalizes Windows-style backslashes", () => {
  23. expect(configEntryNameFromPath("agents\\team\\build.md", AGENT_PREFIXES)).toBe("team/build")
  24. })
  25. test("falls back to basename when no prefix matches", () => {
  26. expect(configEntryNameFromPath("orphaned.md", AGENT_PREFIXES)).toBe("orphaned")
  27. expect(configEntryNameFromPath("anywhere/orphaned.md", [])).toBe("orphaned")
  28. })
  29. // Regression for #25713: a username (or any parent segment) containing
  30. // `agent` or `agents` used to win the substring match before the real
  31. // `agents/` directory could match, leaking the entire intervening path into
  32. // the agent key (e.g. `.config/kirincode/agents/build`). Anchoring at the
  33. // caller via `path.relative(dir, item)` makes this impossible — the relative
  34. // path is always rooted at `agent/` or `agents/`.
  35. test("regression #25713: caller passes relative path; parent /agent/ segment is irrelevant", () => {
  36. const dir = "/home/agent/.config/opencode"
  37. const item = "/home/agent/.config/kirincode/agents/build.md"
  38. const relative = posix.relative(dir, item)
  39. expect(relative).toBe("agents/build.md")
  40. expect(configEntryNameFromPath(relative, AGENT_PREFIXES)).toBe("build")
  41. })
  42. test("regression #25713: parent /agents/ segment is irrelevant", () => {
  43. const dir = "/srv/agents/team/.config/opencode"
  44. const item = "/srv/agents/team/.config/kirincode/agents/build.md"
  45. const relative = posix.relative(dir, item)
  46. expect(configEntryNameFromPath(relative, AGENT_PREFIXES)).toBe("build")
  47. })
  48. })