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 / fixtures / in-repository.ts
GitHub Actions (publish-mods)chore: Update mods/ addd7a6 · 10 days ago History
100 lines · 2.8 KBRaw
1import type { Args, On } from 'claude-code'
2import { mock } from 'claude-code/testing'
3
4import Beneath from './beneath'
5import { gitIn } from './git-in.js'
6import { HINT_DRAWN } from './hint-drawn.js'
7import { keeping } from './keeping.js'
8import { REPOSITORY } from './repository.js'
9import { startsSession } from './starts-session.js'
10
11/**
12 * A session in a repository git answers for from a script (REPOSITORY, in
13 * /work, when none is given), keeping what the plugin does there.
14 *
15 * Kept: each git run, ring move, pane opened, left waiting, left unseen or
16 * closed, status line. The clock starts at 0 and the engine draws the hint.
17 *
18 * The rest of the world is the test's (Beneath). Rewriting the script changes
19 * git's answers.
20 *
21 * @param on the test's `on`
22 * @param script git's output for each invocation whose line holds the key
23 * @param beneath the store, settings, environment, transcript, whether an
24 * open is seated, whether a hunks read is refused
25 * @returns the runs, the ring's moves, the panes opened, left waiting, left
26 * unseen and closed, the statuses, the clock
27 */
28export function inRepository(
29 on: On,
30 script: Readonly<Record<string, string>> = REPOSITORY,
31 beneath: Beneath.Beneath = {},
32) {
33 const runs: Args<'process.run'>[] = []
34 const focused: Args<'ui.focus'>[] = []
35 const statuses: (string | undefined)[] = []
36 const waiting: Args<'ui.open'>[] = []
37 const unseen: Args<'ui.open'>[] = []
38 const opened = keeping<Args<'ui.open'>>()
39 const closed = keeping<Args<'ui.close'>>()
40 const clock = startsSession(on)
41
42 on('process.run', ($, e) => {
43 runs.push(e)
44
45 const refusal = e.argv.includes('--raw') ? beneath.hunksRefusal?.() : null
46 const isRefused = typeof refusal === 'string'
47
48 return isRefused ? { deny: refusal } : { value: gitIn(e.argv, script) }
49 })
50
51 on('ui.focus', (_engine, e) => {
52 focused.push(e)
53
54 return {}
55 })
56
57 on('ui.status', ($, e) => {
58 statuses.push(e.text)
59
60 return { value: undefined }
61 })
62
63 on('ui.open', (engine, e) => {
64 const isWaiting = beneath.isLeftWaiting?.() === true
65 const isUnseen = beneath.isLeftUnseen?.() === true
66
67 if (isUnseen) {
68 unseen.push(e)
69
70 return Beneath.LEFT_UNSEEN
71 }
72
73 if (!isWaiting) {
74 return opened.hook(engine, e)
75 }
76
77 waiting.push(e)
78
79 return Beneath.LEFT_WAITING
80 })
81
82 on('ui.close', closed.hook)
83 on('ui.invalidate', () => ({ value: undefined }))
84 on('ui.render', { component: 'PromptHint' }, () => HINT_DRAWN)
85 on('session.messages', () => ({ value: [...(beneath.messages?.() ?? [])] }))
86 on('settings.read', () => ({ value: beneath.settings ?? {} }))
87 mock.store(on, beneath.stored ?? {})
88 mock.env(on, beneath.env ?? {})
89
90 return {
91 runs,
92 focused,
93 opened: opened.kept,
94 waiting,
95 unseen,
96 closed: closed.kept,
97 statuses,
98 clock,
99 }
100}