@@ -18,6 +18,7 @@ import {bulkUploadThemeAssets, deleteThemeAssets, fetchThemeAssets} from '@shopi
1818import { renderError } from '@shopify/cli-kit/node/ui'
1919import { Operation , type Checksum , type ThemeAsset } from '@shopify/cli-kit/node/themes/types'
2020import { dirname , joinPath } from '@shopify/cli-kit/node/path'
21+ import { recordError } from '@shopify/cli-kit/node/analytics'
2122import { AdminSession } from '@shopify/cli-kit/node/session'
2223
2324import EventEmitter from 'events'
@@ -33,6 +34,13 @@ vi.mock('./asset-ignore.js')
3334vi . mock ( '@shopify/cli-kit/node/themes/api' )
3435vi . mock ( '@shopify/cli-kit/node/ui' )
3536vi . mock ( '@shopify/cli-kit/node/output' )
37+ vi . mock ( '@shopify/cli-kit/node/analytics' , async ( importOriginal ) => {
38+ const actual = await importOriginal < typeof import ( '@shopify/cli-kit/node/analytics' ) > ( )
39+ return {
40+ ...actual ,
41+ recordError : vi . fn ( ) ,
42+ }
43+ } )
3644vi . mock ( './theme-environment/hot-reload/server.js' )
3745
3846beforeEach ( async ( ) => {
@@ -851,6 +859,35 @@ describe('theme-fs', () => {
851859 } )
852860 } )
853861
862+ describe ( 'watcher error handling' , ( ) => {
863+ const themeId = '123'
864+ const adminSession = { token : 'token' } as AdminSession
865+ const root = joinPath ( locationOfThisFile , 'fixtures/theme' )
866+
867+ beforeEach ( ( ) => {
868+ const mockWatcher = new EventEmitter ( )
869+ vi . spyOn ( chokidar , 'watch' ) . mockImplementation ( ( _ ) => {
870+ return mockWatcher as any
871+ } )
872+ } )
873+
874+ test ( 'outputs a warning when the watcher emits an error' , async ( ) => {
875+ // Given
876+ const { outputWarn} = await import ( '@shopify/cli-kit/node/output' )
877+ const themeFileSystem = mountThemeFileSystem ( root )
878+ await themeFileSystem . ready ( )
879+ await themeFileSystem . startWatcher ( themeId , adminSession )
880+
881+ // When
882+ const watcher = chokidar . watch ( '' ) as EventEmitter
883+ watcher . emit ( 'error' , new Error ( 'EMFILE: too many open files' ) )
884+
885+ // Then
886+ expect ( outputWarn ) . toHaveBeenCalledWith ( 'File watcher error: Error: EMFILE: too many open files' )
887+ expect ( recordError ) . toHaveBeenCalledWith ( 'theme-service:file-watcher:error' )
888+ } )
889+ } )
890+
854891 describe ( 'handleSyncUpdate' , ( ) => {
855892 const fileKey = 'assets/test.css'
856893 const themeId = '123'
0 commit comments