|
1 | | -import { describe, expect, test, tier } from 'claude-code/testing' |
| 1 | +import { describe, expect, mock, test, tier } from 'claude-code/testing' |
2 | 2 |
|
3 | 3 | import Hooks from '../hooks' |
4 | 4 | import Fixtures from './fixtures' |
@@ -84,6 +84,70 @@ describe('register', () => { |
84 | 84 | ).toEqual({ blocks: BLOCKS, instructionFiles: [] }) |
85 | 85 | }) |
86 | 86 |
|
| 87 | + for (const [name, args, file, attaches] of [ |
| 88 | + [ |
| 89 | + 'an auto-paginated read', |
| 90 | + {}, |
| 91 | + { content: '# head\nfollow', truncatedByTokenCap: true }, |
| 92 | + true, |
| 93 | + ], |
| 94 | + ['an incomplete line range', {}, { content: '# head', numLines: 1 }, true], |
| 95 | + ['a complete read', {}, {}, false], |
| 96 | + ['an explicit limit', { limit: 1 }, { content: '# head', numLines: 1 }, true], |
| 97 | + [ |
| 98 | + 'an explicit offset', |
| 99 | + { offset: 2 }, |
| 100 | + { content: 'follow the tail rule', numLines: 1, startLine: 2 }, |
| 101 | + true, |
| 102 | + ], |
| 103 | + ['an unstructured result', {}, undefined, false], |
| 104 | + ] as const) { |
| 105 | + test(`a nested AGENTS.md after ${name}`, async ($, on) => { |
| 106 | + const dir = `${Fixtures.SESSION.cwd}/nested` |
| 107 | + const path = `${dir}/AGENTS.md` |
| 108 | + const content = '# head\nfollow the tail rule' |
| 109 | + const started = Fixtures.projectOf( |
| 110 | + on, |
| 111 | + [Fixtures.ancestorOf(dir, 'AGENTS.md', content)], |
| 112 | + [], |
| 113 | + ) |
| 114 | + |
| 115 | + mock.env(on, {}) |
| 116 | + on('session.cwd', () => ({ value: Fixtures.SESSION.cwd })) |
| 117 | + on('tool.call', ($, e) => ({ |
| 118 | + result: |
| 119 | + e.tool === 'Read' && file !== undefined |
| 120 | + ? { |
| 121 | + type: 'text', |
| 122 | + file: Object.assign( |
| 123 | + { |
| 124 | + filePath: e.file_path, |
| 125 | + content, |
| 126 | + numLines: 2, |
| 127 | + startLine: 1, |
| 128 | + totalLines: 2, |
| 129 | + }, |
| 130 | + file, |
| 131 | + ), |
| 132 | + } |
| 133 | + : 'read', |
| 134 | + })) |
| 135 | + |
| 136 | + const direct = await $.tool.call({ tool: 'Read', file_path: path, ...args }) |
| 137 | + const source = { tool: 'Read', file_path: `${dir}/source.ts` } as const |
| 138 | + const after = await $.tool.call(source) |
| 139 | + const repeated = await $.tool.call(source) |
| 140 | + |
| 141 | + expect(direct.context).toBeUndefined() |
| 142 | + expect(after.context).toEqual( |
| 143 | + attaches ? [`Contents of ${path}:\n\n${content}`] : undefined, |
| 144 | + ) |
| 145 | + expect(repeated.context).toBeUndefined() |
| 146 | + |
| 147 | + await started.clock.settle() |
| 148 | + }) |
| 149 | + } |
| 150 | + |
87 | 151 | test( |
88 | 152 | 'the start sends the mode row alone: no walk, no toast', |
89 | 153 | { plugins: [Fixtures.RECORDING] }, |
|
0 commit comments