file-tree.test.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import { beforeAll, describe, expect, mock, test } from "bun:test"
  2. let shouldListRoot: typeof import("./file-tree").shouldListRoot
  3. let shouldListExpanded: typeof import("./file-tree").shouldListExpanded
  4. let dirsToExpand: typeof import("./file-tree").dirsToExpand
  5. beforeAll(async () => {
  6. mock.module("@solidjs/router", () => ({
  7. useNavigate: () => () => undefined,
  8. useParams: () => ({}),
  9. }))
  10. mock.module("@/context/file", () => ({
  11. useFile: () => ({
  12. tree: {
  13. state: () => undefined,
  14. list: () => Promise.resolve(),
  15. children: () => [],
  16. expand: () => {},
  17. collapse: () => {},
  18. },
  19. }),
  20. }))
  21. mock.module("@opencode-ai/ui/collapsible", () => ({
  22. Collapsible: {
  23. Trigger: (props: { children?: unknown }) => props.children,
  24. Content: (props: { children?: unknown }) => props.children,
  25. },
  26. }))
  27. mock.module("@opencode-ai/ui/file-icon", () => ({ FileIcon: () => null }))
  28. mock.module("@opencode-ai/ui/icon", () => ({ Icon: () => null }))
  29. mock.module("@opencode-ai/ui/tooltip", () => ({ Tooltip: (props: { children?: unknown }) => props.children }))
  30. const mod = await import("./file-tree")
  31. shouldListRoot = mod.shouldListRoot
  32. shouldListExpanded = mod.shouldListExpanded
  33. dirsToExpand = mod.dirsToExpand
  34. })
  35. describe("file tree fetch discipline", () => {
  36. test("root lists on mount unless already loaded or loading", () => {
  37. expect(shouldListRoot({ level: 0 })).toBe(true)
  38. expect(shouldListRoot({ level: 0, dir: { loaded: true } })).toBe(false)
  39. expect(shouldListRoot({ level: 0, dir: { loading: true } })).toBe(false)
  40. expect(shouldListRoot({ level: 1 })).toBe(false)
  41. })
  42. test("nested dirs list only when expanded and stale", () => {
  43. expect(shouldListExpanded({ level: 1 })).toBe(false)
  44. expect(shouldListExpanded({ level: 1, dir: { expanded: false } })).toBe(false)
  45. expect(shouldListExpanded({ level: 1, dir: { expanded: true } })).toBe(true)
  46. expect(shouldListExpanded({ level: 1, dir: { expanded: true, loaded: true } })).toBe(false)
  47. expect(shouldListExpanded({ level: 1, dir: { expanded: true, loading: true } })).toBe(false)
  48. expect(shouldListExpanded({ level: 0, dir: { expanded: true } })).toBe(false)
  49. })
  50. test("allowed auto-expand picks only collapsed dirs", () => {
  51. const expanded = new Set<string>()
  52. const filter = { dirs: new Set(["src", "src/components"]) }
  53. const first = dirsToExpand({
  54. level: 0,
  55. filter,
  56. expanded: (dir) => expanded.has(dir),
  57. })
  58. expect(first).toEqual(["src", "src/components"])
  59. for (const dir of first) expanded.add(dir)
  60. const second = dirsToExpand({
  61. level: 0,
  62. filter,
  63. expanded: (dir) => expanded.has(dir),
  64. })
  65. expect(second).toEqual([])
  66. expect(dirsToExpand({ level: 1, filter, expanded: () => false })).toEqual([])
  67. })
  68. })