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 / register.test.ts
176 lines · 5.0 KBRaw
1import {
2 describe,
3 expect,
4 memoryClock,
5 test,
6 textOf,
7 tier,
8} from 'claude-code/testing'
9
10import Limits from '../hooks/limits'
11import Fixtures from './fixtures'
12
13tier('builtin')
14
15describe('register', () => {
16 test('/diff at boot joins the boot probe, then asks again', async ($, on) => {
17 const probes: (readonly string[])[] = []
18 const clock = Fixtures.startsSession(on)
19 on('process.run', async ($, e) => {
20 probes.push(e.argv)
21
22 if (probes.length === 1) {
23 await clock.sleep(Limits.GIT_TIMEOUT_MS)
24
25 return { deny: Fixtures.GIT_HUNG }
26 }
27
28 return { value: Fixtures.NOT_A_REPOSITORY }
29 })
30
31 const booting = $.session.start(Fixtures.SESSION)
32 await clock.advance(0)
33 const ran = $.command.run(Fixtures.DIFF)
34 await clock.advance(0)
35
36 expect(probes, 'the boot probe, which /diff joined').toHaveLength(1)
37
38 await clock.advance(Limits.GIT_TIMEOUT_MS)
39 await booting
40
41 expect(await ran).toEqual({
42 text: expect.stringContaining("isn't in a git repository"),
43 })
44 expect(probes, 'then one more of its own').toHaveLength(2)
45 })
46
47 test('outside a repository /diff says so, opens nothing', async ($, on) => {
48 const opened: string[] = []
49 Fixtures.startsSession(on)
50 on('process.run', () => ({ value: Fixtures.NOT_A_REPOSITORY }))
51 on('ui.open', ($, e, next) => {
52 opened.push(e.id)
53
54 return next(e)
55 })
56
57 await $.session.start(Fixtures.SESSION)
58 const { text } = await $.command.run(Fixtures.DIFF)
59
60 expect(text).toContain("isn't in a git repository")
61 expect(opened).toEqual([])
62 })
63
64 test('a git that never answers is not "no repository"', async ($, on) => {
65 Fixtures.startsSession(on)
66 on('process.run', () => ({ deny: Fixtures.GIT_HUNG }))
67
68 await $.session.start(Fixtures.SESSION)
69 const { text } = await $.command.run(Fixtures.DIFF)
70
71 expect(text).toContain("git didn't answer")
72 })
73
74 test('when the built-in holds /diff, the mod stands down', async ($, on) => {
75 const logged: string[] = []
76 memoryClock(on)
77 on('session.start', ($, e) => ({ cwd: e.cwd }))
78 on('command.register', () => ({ deny: Fixtures.BUILTIN_HOLDS }))
79 on('command.run', () => ({ text: 'the built-in /diff ran' }))
80 on('ui.log', ($, e) => {
81 logged.push(e.text)
82
83 return { value: undefined }
84 })
85
86 await $.session.start(Fixtures.SESSION)
87
88 expect(await $.command.run(Fixtures.DIFF)).toEqual({
89 text: 'the built-in /diff ran',
90 })
91 expect(logged).toEqual([])
92 })
93
94 test('a refusal the built-in did not cause is said aloud', async ($, on) => {
95 const logged: string[] = []
96 memoryClock(on)
97 on('session.start', ($, e) => ({ cwd: e.cwd }))
98 on('command.register', () => ({
99 deny: '32 commands are registered already',
100 }))
101 on('ui.log', ($, e) => {
102 logged.push(e.text)
103
104 return { value: undefined }
105 })
106
107 await $.session.start(Fixtures.SESSION)
108
109 expect(logged).toEqual([
110 'could not register /diff: diff: $.command.register: 32 commands are ' +
111 'registered already; the diff panel is unavailable this session',
112 ])
113 })
114
115 test('/diff opens the pane over the session changes', async ($, on) => {
116 const world = Fixtures.inRepository(on)
117
118 await $.session.start(Fixtures.SESSION)
119
120 expect(await $.command.run(Fixtures.DIFF)).toEqual({})
121 expect(world.opened.map(pane => pane.id)).toEqual(['diff'])
122
123 await world.clock.advance(Fixtures.SETTLE_MS)
124 const drawn = textOf(await $.ui.render(Fixtures.PANE))
125
126 expect(drawn).toContain('1 file changed')
127 expect(drawn).toContain('app.ts')
128 })
129
130 test('the close button closes the pane; /diff reopens it', async ($, on) => {
131 const world = Fixtures.inRepository(on)
132
133 await $.session.start(Fixtures.SESSION)
134 await $.command.run(Fixtures.DIFF)
135 await world.clock.advance(Fixtures.SETTLE_MS)
136 await $.ui.render(Fixtures.PANE)
137
138 expect(await $.ui.press({ plugin: 'diff', key: 'close' })).toEqual({
139 element: 'close',
140 })
141
142 await world.clock.advance(0)
143
144 expect(world.closed.map(pane => pane.id)).toEqual(['diff'])
145 expect(await $.command.run(Fixtures.DIFF)).toEqual({})
146 expect(world.opened.map(pane => pane.id)).toEqual(['diff', 'diff'])
147 })
148
149 test('a wide terminal opens the pane at the first edit', async ($, on) => {
150 const world = Fixtures.inRepository(on)
151 on('tool.call', () => ({ result: 'edited' }))
152
153 await $.session.start(Fixtures.SESSION)
154 await $.ui.render(Fixtures.HINT)
155 await $.tool.call({
156 tool: 'Edit',
157 file_path: '/work/app.ts',
158 old_string: '1',
159 new_string: '2',
160 })
161 await world.clock.advance(Fixtures.SETTLE_MS)
162
163 expect(world.opened.map(pane => pane.id)).toEqual(['diff'])
164 })
165
166 test('/clear closes the pane it finds open', async ($, on) => {
167 const world = Fixtures.inRepository(on)
168 on('command.run', { command: 'clear' }, () => ({}))
169
170 await $.session.start(Fixtures.SESSION)
171 await $.command.run(Fixtures.DIFF)
172 await $.command.run(Fixtures.CLEAR)
173
174 expect(world.closed.map(pane => pane.id)).toEqual(['diff'])
175 })
176})