@@ -73,13 +73,33 @@ describe("RooConfigService", () => {
7373 } )
7474
7575 it ( "should return false for non-existing path" , async ( ) => {
76- mockStat . mockRejectedValue ( new Error ( "ENOENT" ) )
76+ const error = new Error ( "ENOENT" ) as any
77+ error . code = "ENOENT"
78+ mockStat . mockRejectedValue ( error )
7779
7880 const result = await directoryExists ( "/non/existing/path" )
7981
8082 expect ( result ) . toBe ( false )
8183 } )
8284
85+ it ( "should return false for ENOTDIR error" , async ( ) => {
86+ const error = new Error ( "ENOTDIR" ) as any
87+ error . code = "ENOTDIR"
88+ mockStat . mockRejectedValue ( error )
89+
90+ const result = await directoryExists ( "/not/a/directory" )
91+
92+ expect ( result ) . toBe ( false )
93+ } )
94+
95+ it ( "should throw unexpected errors" , async ( ) => {
96+ const error = new Error ( "Permission denied" ) as any
97+ error . code = "EACCES"
98+ mockStat . mockRejectedValue ( error )
99+
100+ await expect ( directoryExists ( "/permission/denied" ) ) . rejects . toThrow ( "Permission denied" )
101+ } )
102+
83103 it ( "should return false for files" , async ( ) => {
84104 mockStat . mockResolvedValue ( { isDirectory : ( ) => false } as any )
85105
@@ -100,13 +120,33 @@ describe("RooConfigService", () => {
100120 } )
101121
102122 it ( "should return false for non-existing file" , async ( ) => {
103- mockStat . mockRejectedValue ( new Error ( "ENOENT" ) )
123+ const error = new Error ( "ENOENT" ) as any
124+ error . code = "ENOENT"
125+ mockStat . mockRejectedValue ( error )
104126
105127 const result = await fileExists ( "/non/existing/file.txt" )
106128
107129 expect ( result ) . toBe ( false )
108130 } )
109131
132+ it ( "should return false for ENOTDIR error" , async ( ) => {
133+ const error = new Error ( "ENOTDIR" ) as any
134+ error . code = "ENOTDIR"
135+ mockStat . mockRejectedValue ( error )
136+
137+ const result = await fileExists ( "/not/a/directory/file.txt" )
138+
139+ expect ( result ) . toBe ( false )
140+ } )
141+
142+ it ( "should throw unexpected errors" , async ( ) => {
143+ const error = new Error ( "Permission denied" ) as any
144+ error . code = "EACCES"
145+ mockStat . mockRejectedValue ( error )
146+
147+ await expect ( fileExists ( "/permission/denied/file.txt" ) ) . rejects . toThrow ( "Permission denied" )
148+ } )
149+
110150 it ( "should return false for directories" , async ( ) => {
111151 mockStat . mockResolvedValue ( { isFile : ( ) => false } as any )
112152
@@ -127,12 +167,42 @@ describe("RooConfigService", () => {
127167 } )
128168
129169 it ( "should return null for non-existing file" , async ( ) => {
130- mockReadFile . mockRejectedValue ( new Error ( "ENOENT" ) )
170+ const error = new Error ( "ENOENT" ) as any
171+ error . code = "ENOENT"
172+ mockReadFile . mockRejectedValue ( error )
131173
132174 const result = await readFileIfExists ( "/non/existing/file.txt" )
133175
134176 expect ( result ) . toBe ( null )
135177 } )
178+
179+ it ( "should return null for ENOTDIR error" , async ( ) => {
180+ const error = new Error ( "ENOTDIR" ) as any
181+ error . code = "ENOTDIR"
182+ mockReadFile . mockRejectedValue ( error )
183+
184+ const result = await readFileIfExists ( "/not/a/directory/file.txt" )
185+
186+ expect ( result ) . toBe ( null )
187+ } )
188+
189+ it ( "should return null for EISDIR error" , async ( ) => {
190+ const error = new Error ( "EISDIR" ) as any
191+ error . code = "EISDIR"
192+ mockReadFile . mockRejectedValue ( error )
193+
194+ const result = await readFileIfExists ( "/is/a/directory" )
195+
196+ expect ( result ) . toBe ( null )
197+ } )
198+
199+ it ( "should throw unexpected errors" , async ( ) => {
200+ const error = new Error ( "Permission denied" ) as any
201+ error . code = "EACCES"
202+ mockReadFile . mockRejectedValue ( error )
203+
204+ await expect ( readFileIfExists ( "/permission/denied/file.txt" ) ) . rejects . toThrow ( "Permission denied" )
205+ } )
136206 } )
137207
138208 describe ( "getRooDirectoriesForCwd" , ( ) => {
@@ -147,7 +217,9 @@ describe("RooConfigService", () => {
147217
148218 describe ( "loadConfiguration" , ( ) => {
149219 it ( "should load global configuration only when project does not exist" , async ( ) => {
150- mockReadFile . mockResolvedValueOnce ( "global content" ) . mockRejectedValueOnce ( new Error ( "ENOENT" ) )
220+ const error = new Error ( "ENOENT" ) as any
221+ error . code = "ENOENT"
222+ mockReadFile . mockResolvedValueOnce ( "global content" ) . mockRejectedValueOnce ( error )
151223
152224 const result = await loadConfiguration ( "rules/rules.md" , "/project/path" )
153225
@@ -159,7 +231,9 @@ describe("RooConfigService", () => {
159231 } )
160232
161233 it ( "should load project configuration only when global does not exist" , async ( ) => {
162- mockReadFile . mockRejectedValueOnce ( new Error ( "ENOENT" ) ) . mockResolvedValueOnce ( "project content" )
234+ const error = new Error ( "ENOENT" ) as any
235+ error . code = "ENOENT"
236+ mockReadFile . mockRejectedValueOnce ( error ) . mockResolvedValueOnce ( "project content" )
163237
164238 const result = await loadConfiguration ( "rules/rules.md" , "/project/path" )
165239
@@ -183,7 +257,9 @@ describe("RooConfigService", () => {
183257 } )
184258
185259 it ( "should return empty merged content when neither exists" , async ( ) => {
186- mockReadFile . mockRejectedValueOnce ( new Error ( "ENOENT" ) ) . mockRejectedValueOnce ( new Error ( "ENOENT" ) )
260+ const error = new Error ( "ENOENT" ) as any
261+ error . code = "ENOENT"
262+ mockReadFile . mockRejectedValueOnce ( error ) . mockRejectedValueOnce ( error )
187263
188264 const result = await loadConfiguration ( "rules/rules.md" , "/project/path" )
189265
@@ -194,6 +270,25 @@ describe("RooConfigService", () => {
194270 } )
195271 } )
196272
273+ it ( "should propagate unexpected errors from global file read" , async ( ) => {
274+ const error = new Error ( "Permission denied" ) as any
275+ error . code = "EACCES"
276+ mockReadFile . mockRejectedValueOnce ( error )
277+
278+ await expect ( loadConfiguration ( "rules/rules.md" , "/project/path" ) ) . rejects . toThrow ( "Permission denied" )
279+ } )
280+
281+ it ( "should propagate unexpected errors from project file read" , async ( ) => {
282+ const globalError = new Error ( "ENOENT" ) as any
283+ globalError . code = "ENOENT"
284+ const projectError = new Error ( "Permission denied" ) as any
285+ projectError . code = "EACCES"
286+
287+ mockReadFile . mockRejectedValueOnce ( globalError ) . mockRejectedValueOnce ( projectError )
288+
289+ await expect ( loadConfiguration ( "rules/rules.md" , "/project/path" ) ) . rejects . toThrow ( "Permission denied" )
290+ } )
291+
197292 it ( "should use correct file paths" , async ( ) => {
198293 mockReadFile . mockResolvedValue ( "content" )
199294
0 commit comments