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