spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

claude-code / mods / diff / tests / git / probes / datings-of.test.ts
119 lines · 3.0 KBRaw
1import { describe, expect, test, tier } from 'claude-code/testing'
2
3import Git from '../../../hooks/git'
4import Fixtures from '../../fixtures'
5
6tier('builtin')
7
8describe('datings-of', () => {
9 type Listing = ReadonlyMap<string, Git.EntryKind>
10
11 const LISTINGS: ReadonlyMap<string, Listing> = new Map<string, Listing>([
12 [
13 '/repo',
14 new Map([
15 ['a', 'dir'],
16 ['b', 'dir'],
17 ['c', 'dir'],
18 ['deep', 'dir'],
19 ]),
20 ],
21 ['/repo/a', new Map([['x', 'file']])],
22 ['/repo/b', new Map([['y', 'file']])],
23 ['/repo/c', new Map([['z', 'file']])],
24 [
25 '/repo/deep',
26 new Map([
27 ['x.ts', 'file'],
28 ['y.txt', 'file'],
29 ]),
30 ],
31 ])
32
33 function probeOf(budget: number) {
34 const listed: string[] = []
35 const statted: string[] = []
36
37 const probe = Git.stampProbeOf(
38 {
39 entryKindsOf: dir => {
40 listed.push(dir)
41
42 return Promise.resolve(LISTINGS.get(dir) ?? null)
43 },
44 mtimeOf: path => {
45 statted.push(path)
46
47 return Promise.resolve(Fixtures.BEFORE_SESSION_MS)
48 },
49 },
50 '/repo',
51 budget,
52 )
53
54 return { probe, listed, statted }
55 }
56
57 const depsOf = (run: Git.GitRun, probe: Git.StampProbe): Git.GitDeps => ({
58 run,
59 repository: Fixtures.CHECKOUT,
60 mtimeOf: probe.mtimeOf,
61 entryKindsOf: () => Promise.resolve(null),
62 sessionStartMs: Fixtures.GIT_SESSION_START_MS,
63 onBranchBase: () => undefined,
64 })
65
66 function contextOf(probe: Git.StampProbe, listing: string) {
67 const { run } = Fixtures.scriptedGitOf({ 'ls-files': Fixtures.ok(listing) })
68
69 return { run, deps: depsOf(run, probe), stamps: probe }
70 }
71
72 test('a spent budget answers unlisted, and stats nothing there', async () => {
73 const recorded = probeOf(Fixtures.TWO_LISTINGS_BUDGET)
74
75 expect([
76 ...(await Git.datingsOf(
77 {
78 stamps: recorded.probe,
79 deps: { sessionStartMs: Fixtures.GIT_SESSION_START_MS },
80 },
81 ['a/x', 'b/y', 'c/z', 'missing'],
82 )),
83 ]).toEqual([
84 ['a/x', 'pre-session'],
85 ['b/y', 'unlisted'],
86 ['c/z', 'unlisted'],
87 ['missing', 'session'],
88 ])
89
90 expect(recorded.listed).toEqual(['/repo', '/repo/a'])
91 expect(recorded.statted).toEqual(['/repo/a/x'])
92 })
93
94 test('an unlisted tracked row stays session work', async () => {
95 const context = contextOf(probeOf(Fixtures.ROOT_ONLY_BUDGET).probe, '')
96 const rows = await Git.tagPreSession(context, [Fixtures.TRACKED_ROW])
97
98 expect(context.stamps.base).toBe('/repo')
99 expect(rows.map(row => row.isPreSession)).toEqual([false])
100 })
101
102 test('an unlisted untracked file reads as pre-session', async () => {
103 const context = contextOf(
104 probeOf(Fixtures.ROOT_ONLY_BUDGET).probe,
105 'deep/y.txt\0',
106 )
107
108 const rows = await Git.untrackedFiles(context, {
109 slots: 1,
110 scope: 'with-pre-session',
111 })
112
113 expect(context.stamps.base).toBe('/repo')
114
115 expect(rows?.map(row => [row.path, row.isPreSession])).toEqual([
116 ['deep/y.txt', true],
117 ])
118 })
119})