@@ -89,6 +89,59 @@ describe("SimpleInstaller", () => {
8989 expect ( writtenData . customModes . find ( ( m : any ) => m . slug === "test" ) ) . toBeDefined ( )
9090 } )
9191
92+ it ( "should handle empty .roomodes file" , async ( ) => {
93+ // Empty file content
94+ mockFs . readFile . mockResolvedValueOnce ( "" )
95+ mockFs . writeFile . mockResolvedValueOnce ( undefined as any )
96+
97+ const result = await installer . installItem ( mockModeItem , { target : "project" } )
98+
99+ expect ( result . filePath ) . toBe ( path . join ( "/test/workspace" , ".roomodes" ) )
100+ expect ( mockFs . writeFile ) . toHaveBeenCalled ( )
101+
102+ // Verify the written content contains the new mode
103+ const writtenContent = mockFs . writeFile . mock . calls [ 0 ] [ 1 ] as string
104+ const writtenData = yaml . parse ( writtenContent )
105+ expect ( writtenData . customModes ) . toHaveLength ( 1 )
106+ expect ( writtenData . customModes [ 0 ] . slug ) . toBe ( "test" )
107+ } )
108+
109+ it ( "should handle .roomodes file with null content" , async ( ) => {
110+ // File exists but yaml.parse returns null
111+ mockFs . readFile . mockResolvedValueOnce ( "---\n" )
112+ mockFs . writeFile . mockResolvedValueOnce ( undefined as any )
113+
114+ const result = await installer . installItem ( mockModeItem , { target : "project" } )
115+
116+ expect ( result . filePath ) . toBe ( path . join ( "/test/workspace" , ".roomodes" ) )
117+ expect ( mockFs . writeFile ) . toHaveBeenCalled ( )
118+
119+ // Verify the written content contains the new mode
120+ const writtenContent = mockFs . writeFile . mock . calls [ 0 ] [ 1 ] as string
121+ const writtenData = yaml . parse ( writtenContent )
122+ expect ( writtenData . customModes ) . toHaveLength ( 1 )
123+ expect ( writtenData . customModes [ 0 ] . slug ) . toBe ( "test" )
124+ } )
125+
126+ it ( "should handle .roomodes file without customModes property" , async ( ) => {
127+ // File has valid YAML but no customModes property
128+ const contentWithoutCustomModes = yaml . stringify ( { someOtherProperty : "value" } )
129+ mockFs . readFile . mockResolvedValueOnce ( contentWithoutCustomModes )
130+ mockFs . writeFile . mockResolvedValueOnce ( undefined as any )
131+
132+ const result = await installer . installItem ( mockModeItem , { target : "project" } )
133+
134+ expect ( result . filePath ) . toBe ( path . join ( "/test/workspace" , ".roomodes" ) )
135+ expect ( mockFs . writeFile ) . toHaveBeenCalled ( )
136+
137+ // Verify the written content contains the new mode and preserves other properties
138+ const writtenContent = mockFs . writeFile . mock . calls [ 0 ] [ 1 ] as string
139+ const writtenData = yaml . parse ( writtenContent )
140+ expect ( writtenData . customModes ) . toHaveLength ( 1 )
141+ expect ( writtenData . customModes [ 0 ] . slug ) . toBe ( "test" )
142+ expect ( writtenData . someOtherProperty ) . toBe ( "value" )
143+ } )
144+
92145 it ( "should throw error when .roomodes contains invalid YAML" , async ( ) => {
93146 const invalidYaml = "invalid: yaml: content: {"
94147
@@ -224,5 +277,52 @@ describe("SimpleInstaller", () => {
224277
225278 expect ( mockFs . writeFile ) . not . toHaveBeenCalled ( )
226279 } )
280+
281+ it ( "should handle empty .roomodes file during removal" , async ( ) => {
282+ // Empty file content
283+ mockFs . readFile . mockResolvedValueOnce ( "" )
284+ mockFs . writeFile . mockResolvedValueOnce ( undefined as any )
285+
286+ // Should not throw
287+ await installer . removeItem ( mockModeItem , { target : "project" } )
288+
289+ // Should write back a valid structure with empty customModes
290+ expect ( mockFs . writeFile ) . toHaveBeenCalled ( )
291+ const writtenContent = mockFs . writeFile . mock . calls [ 0 ] [ 1 ] as string
292+ const writtenData = yaml . parse ( writtenContent )
293+ expect ( writtenData . customModes ) . toEqual ( [ ] )
294+ } )
295+
296+ it ( "should handle .roomodes file with null content during removal" , async ( ) => {
297+ // File exists but yaml.parse returns null
298+ mockFs . readFile . mockResolvedValueOnce ( "---\n" )
299+ mockFs . writeFile . mockResolvedValueOnce ( undefined as any )
300+
301+ // Should not throw
302+ await installer . removeItem ( mockModeItem , { target : "project" } )
303+
304+ // Should write back a valid structure with empty customModes
305+ expect ( mockFs . writeFile ) . toHaveBeenCalled ( )
306+ const writtenContent = mockFs . writeFile . mock . calls [ 0 ] [ 1 ] as string
307+ const writtenData = yaml . parse ( writtenContent )
308+ expect ( writtenData . customModes ) . toEqual ( [ ] )
309+ } )
310+
311+ it ( "should handle .roomodes file without customModes property during removal" , async ( ) => {
312+ // File has valid YAML but no customModes property
313+ const contentWithoutCustomModes = yaml . stringify ( { someOtherProperty : "value" } )
314+ mockFs . readFile . mockResolvedValueOnce ( contentWithoutCustomModes )
315+ mockFs . writeFile . mockResolvedValueOnce ( undefined as any )
316+
317+ // Should not throw
318+ await installer . removeItem ( mockModeItem , { target : "project" } )
319+
320+ // Should write back the file with the same content (no modes to remove)
321+ expect ( mockFs . writeFile ) . toHaveBeenCalled ( )
322+ const writtenContent = mockFs . writeFile . mock . calls [ 0 ] [ 1 ] as string
323+ const writtenData = yaml . parse ( writtenContent )
324+ expect ( writtenData . customModes ) . toEqual ( [ ] )
325+ expect ( writtenData . someOtherProperty ) . toBe ( "value" )
326+ } )
227327 } )
228328} )
0 commit comments