@@ -3,19 +3,15 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync, rmSync } from 'node
33import { resolve } from 'node:path' ;
44import { tmpdir } from 'node:os' ;
55import { randomBytes } from 'node:crypto' ;
6-
7- /**
8- * Test the .claude/settings.local.json injection behavior in workspace setup.
9- * Since injectLocalSettings is not exported, we replicate its logic here to verify the contract.
10- */
6+ import { injectLocalSettings } from '../workspace/manager.js' ;
117
128function createTempWorkspace ( ) : string {
139 const dir = resolve ( tmpdir ( ) , `ws-test-${ randomBytes ( 4 ) . toString ( 'hex' ) } ` ) ;
1410 mkdirSync ( dir , { recursive : true } ) ;
1511 return dir ;
1612}
1713
18- describe ( 'workspace settings.local.json injection ' , ( ) => {
14+ describe ( 'injectLocalSettings ' , ( ) => {
1915 let workspacePath : string ;
2016
2117 beforeEach ( ( ) => {
@@ -26,80 +22,52 @@ describe('workspace settings.local.json injection', () => {
2622 rmSync ( workspacePath , { recursive : true , force : true } ) ;
2723 } ) ;
2824
29- it ( 'should create .claude/settings.local.json with permission whitelist' , async ( ) => {
30- // Simulate what injectLocalSettings does
31- const claudeDir = resolve ( workspacePath , '.claude' ) ;
32- const settingsPath = resolve ( claudeDir , 'settings.local.json' ) ;
33-
34- // Import the manager module to call setupWorkspace indirectly won't work without git,
35- // so we verify the contract: after injection, the file should contain expected permissions
36- mkdirSync ( claudeDir , { recursive : true } ) ;
37-
38- const settings = {
39- permissions : {
40- allow : [
41- 'Bash(git *)' ,
42- 'Bash(npm *)' ,
43- 'Bash(npx *)' ,
44- 'Bash(node *)' ,
45- 'Bash(cat *)' ,
46- 'Bash(ls *)' ,
47- 'Bash(find *)' ,
48- 'Bash(grep *)' ,
49- 'Bash(echo *)' ,
50- 'Bash(pwd)' ,
51- 'Bash(which *)' ,
52- 'Bash(gh *)' ,
53- ] ,
54- } ,
55- } ;
56- writeFileSync ( settingsPath , JSON . stringify ( settings , null , 2 ) + '\n' ) ;
25+ it ( 'should create .claude/settings.local.json with permission whitelist' , ( ) => {
26+ injectLocalSettings ( workspacePath ) ;
5727
28+ const settingsPath = resolve ( workspacePath , '.claude' , 'settings.local.json' ) ;
5829 expect ( existsSync ( settingsPath ) ) . toBe ( true ) ;
30+
5931 const content = JSON . parse ( readFileSync ( settingsPath , 'utf-8' ) ) ;
6032 expect ( content . permissions . allow ) . toContain ( 'Bash(git *)' ) ;
6133 expect ( content . permissions . allow ) . toContain ( 'Bash(npm *)' ) ;
34+ expect ( content . permissions . allow ) . toContain ( 'Bash(npx *)' ) ;
6235 expect ( content . permissions . allow ) . toContain ( 'Bash(gh *)' ) ;
6336 } ) ;
6437
38+ it ( 'should create .claude directory if it does not exist' , ( ) => {
39+ const claudeDir = resolve ( workspacePath , '.claude' ) ;
40+ expect ( existsSync ( claudeDir ) ) . toBe ( false ) ;
41+
42+ injectLocalSettings ( workspacePath ) ;
43+
44+ expect ( existsSync ( claudeDir ) ) . toBe ( true ) ;
45+ expect ( existsSync ( resolve ( claudeDir , 'settings.local.json' ) ) ) . toBe ( true ) ;
46+ } ) ;
47+
6548 it ( 'should not overwrite existing settings.local.json' , ( ) => {
6649 const claudeDir = resolve ( workspacePath , '.claude' ) ;
6750 const settingsPath = resolve ( claudeDir , 'settings.local.json' ) ;
6851
69- // Pre-create a custom settings file
7052 mkdirSync ( claudeDir , { recursive : true } ) ;
7153 const customSettings = { permissions : { allow : [ 'Bash(custom *)' ] } } ;
7254 writeFileSync ( settingsPath , JSON . stringify ( customSettings ) ) ;
7355
74- // Verify existing file is preserved ( injectLocalSettings skips if exists)
75- expect ( existsSync ( settingsPath ) ) . toBe ( true ) ;
56+ injectLocalSettings ( workspacePath ) ;
57+
7658 const content = JSON . parse ( readFileSync ( settingsPath , 'utf-8' ) ) ;
7759 expect ( content . permissions . allow ) . toEqual ( [ 'Bash(custom *)' ] ) ;
7860 } ) ;
7961
80- it ( 'should include git commands critical for bot workflow' , ( ) => {
81- const requiredPatterns = [ 'Bash(git *)' , 'Bash(npm *)' , 'Bash(npx *)' ] ;
82- const settings = {
83- permissions : {
84- allow : [
85- 'Bash(git *)' ,
86- 'Bash(npm *)' ,
87- 'Bash(npx *)' ,
88- 'Bash(node *)' ,
89- 'Bash(cat *)' ,
90- 'Bash(ls *)' ,
91- 'Bash(find *)' ,
92- 'Bash(grep *)' ,
93- 'Bash(echo *)' ,
94- 'Bash(pwd)' ,
95- 'Bash(which *)' ,
96- 'Bash(gh *)' ,
97- ] ,
98- } ,
99- } ;
100-
101- for ( const pattern of requiredPatterns ) {
102- expect ( settings . permissions . allow ) . toContain ( pattern ) ;
62+ it ( 'should include all critical bot workflow commands' , ( ) => {
63+ injectLocalSettings ( workspacePath ) ;
64+
65+ const settingsPath = resolve ( workspacePath , '.claude' , 'settings.local.json' ) ;
66+ const content = JSON . parse ( readFileSync ( settingsPath , 'utf-8' ) ) ;
67+
68+ const required = [ 'Bash(git *)' , 'Bash(npm *)' , 'Bash(npx *)' , 'Bash(node *)' , 'Bash(gh *)' ] ;
69+ for ( const pattern of required ) {
70+ expect ( content . permissions . allow ) . toContain ( pattern ) ;
10371 }
10472 } ) ;
10573} ) ;
0 commit comments