file-tree.test.ts 2.9 KB

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