44
55import { DatabaseSync } from "node:sqlite" ;
66import type { DomainEvent } from "@coder-studio/core" ;
7+ import chokidar , { type FSWatcher } from "chokidar" ;
78import { mkdir , rmdir } from "fs/promises" ;
89import { tmpdir } from "os" ;
910import { join } from "path" ;
@@ -20,6 +21,7 @@ describe("WorkspaceManager", () => {
2021 emit : ( event : DomainEvent ) => void ;
2122 on : ( ) => ( ) => void ;
2223 } ;
24+ let watchSpy : ReturnType < typeof vi . spyOn < typeof chokidar , "watch" > > ;
2325
2426 beforeEach ( async ( ) => {
2527 // Create test directory
@@ -53,10 +55,18 @@ describe("WorkspaceManager", () => {
5355 on : ( ) => ( ) => { } ,
5456 } ;
5557
58+ watchSpy = vi . spyOn ( chokidar , "watch" ) . mockReturnValue ( {
59+ on ( ) {
60+ return this ;
61+ } ,
62+ close : vi . fn ( ) . mockResolvedValue ( undefined ) ,
63+ } as unknown as FSWatcher ) ;
64+
5665 manager = new WorkspaceManager ( { db, eventBus } ) ;
5766 } ) ;
5867
5968 afterEach ( async ( ) => {
69+ watchSpy . mockRestore ( ) ;
6070 try {
6171 db . close ( ) ;
6272 await rmdir ( testDir ) ;
@@ -224,6 +234,46 @@ describe("WorkspaceManager", () => {
224234 } ) ;
225235 } ) ;
226236
237+ describe ( "hydrateWatchers" , ( ) => {
238+ it ( "starts file watchers for persisted workspaces" , async ( ) => {
239+ const persisted = await manager . open ( { path : testDir } ) ;
240+ const broadcaster = { broadcast : vi . fn ( ) } ;
241+ const restoredManager = new WorkspaceManager ( { db, eventBus, broadcaster } ) ;
242+
243+ restoredManager . hydrateWatchers ( ) ;
244+
245+ expect ( watchSpy ) . toHaveBeenCalledTimes ( 1 ) ;
246+ expect ( watchSpy ) . toHaveBeenCalledWith (
247+ testDir ,
248+ expect . objectContaining ( {
249+ ignoreInitial : true ,
250+ persistent : true ,
251+ } )
252+ ) ;
253+ expect (
254+ ( restoredManager as unknown as { watchers : Map < string , unknown > } ) . watchers . has (
255+ persisted . id
256+ )
257+ ) . toBe ( true ) ;
258+ } ) ;
259+
260+ it ( "does not create duplicate watchers when called multiple times" , async ( ) => {
261+ const persisted = await manager . open ( { path : testDir } ) ;
262+ const broadcaster = { broadcast : vi . fn ( ) } ;
263+ const restoredManager = new WorkspaceManager ( { db, eventBus, broadcaster } ) ;
264+
265+ restoredManager . hydrateWatchers ( ) ;
266+ restoredManager . hydrateWatchers ( ) ;
267+
268+ expect ( watchSpy ) . toHaveBeenCalledTimes ( 1 ) ;
269+ expect (
270+ ( restoredManager as unknown as { watchers : Map < string , unknown > } ) . watchers . has (
271+ persisted . id
272+ )
273+ ) . toBe ( true ) ;
274+ } ) ;
275+ } ) ;
276+
227277 describe ( "updateUiState" , ( ) => {
228278 it ( "updates workspace pane layout and emits workspace meta changed" , async ( ) => {
229279 const workspace = await manager . open ( { path : testDir } ) ;
0 commit comments