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
189 lines · 5.0 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 over the session changes', 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 expect(world.opened.map(pane => pane.id)).toEqual(['diff'])
130
131 await world.clock.advance(Fixtures.SETTLE_MS)
132
133 const drawn = Fixtures.textOf(await $.ui.render(Fixtures.PANE))
134
135 expect(drawn).toContain('1 file changed')
136 expect(drawn).toContain('app.ts')
137 })
138
139 test('the close button closes the pane; /diff reopens it', async ($, on) => {
140 const world = Fixtures.inRepository(on)
141
142 await $.session.start(Fixtures.SESSION)
143 await $.command.run(Fixtures.DIFF)
144 await world.clock.advance(Fixtures.SETTLE_MS)
145 await $.ui.render(Fixtures.PANE)
146
147 expect(await $.ui.press({ plugin: 'diff', key: 'close' })).toEqual({
148 element: 'close',
149 })
150
151 await world.clock.settle()
152
153 expect(world.closed.map(pane => pane.id)).toEqual(['diff'])
154 expect(await $.command.run(Fixtures.DIFF)).toEqual({})
155 expect(world.opened.map(pane => pane.id)).toEqual(['diff', 'diff'])
156 })
157
158 test('a wide terminal opens the pane at the first edit', async ($, on) => {
159 const world = Fixtures.inRepository(on)
160
161 on('tool.call', () => ({ result: 'edited' }))
162
163 await $.session.start(Fixtures.SESSION)
164 await $.ui.render(Fixtures.HINT)
165
166 await $.tool.call({
167 tool: 'Edit',
168 file_path: '/work/app.ts',
169 old_string: '1',
170 new_string: '2',
171 })
172
173 await world.clock.advance(Fixtures.SETTLE_MS)
174
175 expect(world.opened.map(pane => pane.id)).toEqual(['diff'])
176 })
177
178 test('/clear closes the pane it finds open', async ($, on) => {
179 const world = Fixtures.inRepository(on)
180
181 on('command.run', { command: 'clear' }, () => ({}))
182
183 await $.session.start(Fixtures.SESSION)
184 await $.command.run(Fixtures.DIFF)
185 await $.command.run(Fixtures.CLEAR)
186
187 expect(world.closed.map(pane => pane.id)).toEqual(['diff'])
188 })
189})