import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { $connection } from '@/store/session' import { desktopGitRoot, readDesktopDir, readDesktopFileDataUrl, readDesktopFileText, selectDesktopPaths, setDesktopFsRemotePicker } from './desktop-fs' const readDir = vi.fn(async () => ({ entries: [{ name: 'local', path: '/local', isDirectory: true }] })) const readFileText = vi.fn(async () => ({ path: '/local/file.txt', text: 'local', byteSize: 5 })) const readFileDataUrl = vi.fn(async () => 'data:text/plain;base64,bG9jYWw=') const gitRoot = vi.fn(async () => '/local') const selectPaths = vi.fn(async () => ['/local']) const api = vi.fn(async ({ path }: { path: string }) => { if (path.startsWith('/api/fs/list?')) return { entries: [{ name: 'remote', path: '/remote', isDirectory: true }] } if (path.startsWith('/api/fs/read-text?')) return { path: '/remote/file.txt', text: 'remote', byteSize: 6 } if (path.startsWith('/api/fs/read-data-url?')) return { dataUrl: 'data:text/plain;base64,cmVtb3Rl' } if (path.startsWith('/api/fs/git-root?')) return { root: '/remote' } throw new Error(`unexpected path ${path}`) }) function stubBridge() { vi.stubGlobal('window', { hermesDesktop: { api, gitRoot, readDir, readFileDataUrl, readFileText, selectPaths } }) } describe('desktop filesystem facade', () => { beforeEach(() => { stubBridge() $connection.set(null) }) afterEach(() => { vi.unstubAllGlobals() vi.clearAllMocks() $connection.set(null) setDesktopFsRemotePicker(null) }) it('uses local Electron filesystem methods in local mode', async () => { $connection.set({ mode: 'local' } as never) await expect(readDesktopDir('/work')).resolves.toEqual({ entries: [{ name: 'local', path: '/local', isDirectory: true }] }) await expect(readDesktopFileText('/work/file.txt')).resolves.toMatchObject({ text: 'local' }) await expect(readDesktopFileDataUrl('/work/file.txt')).resolves.toBe('data:text/plain;base64,bG9jYWw=') await expect(desktopGitRoot('/work')).resolves.toBe('/local') await expect(selectDesktopPaths({ directories: true })).resolves.toEqual(['/local']) expect(readDir).toHaveBeenCalledWith('/work') expect(readFileText).toHaveBeenCalledWith('/work/file.txt') expect(readFileDataUrl).toHaveBeenCalledWith('/work/file.txt') expect(gitRoot).toHaveBeenCalledWith('/work') expect(selectPaths).toHaveBeenCalledWith({ directories: true }) expect(api).not.toHaveBeenCalled() }) it('routes filesystem reads through authenticated backend REST in remote mode', async () => { $connection.set({ mode: 'remote' } as never) await expect(readDesktopDir('/home/user/project')).resolves.toMatchObject({ entries: [{ name: 'remote' }] }) await expect(readDesktopFileText('/home/user/project/a b.txt')).resolves.toMatchObject({ text: 'remote' }) await expect(readDesktopFileDataUrl('/home/user/project/a b.txt')).resolves.toBe('data:text/plain;base64,cmVtb3Rl') await expect(desktopGitRoot('/home/user/project')).resolves.toBe('/remote') expect(api).toHaveBeenCalledWith({ path: '/api/fs/list?path=%2Fhome%2Fuser%2Fproject' }) expect(api).toHaveBeenCalledWith({ path: '/api/fs/read-text?path=%2Fhome%2Fuser%2Fproject%2Fa%20b.txt' }) expect(api).toHaveBeenCalledWith({ path: '/api/fs/read-data-url?path=%2Fhome%2Fuser%2Fproject%2Fa%20b.txt' }) expect(api).toHaveBeenCalledWith({ path: '/api/fs/git-root?path=%2Fhome%2Fuser%2Fproject' }) expect(readDir).not.toHaveBeenCalled() expect(readFileText).not.toHaveBeenCalled() expect(readFileDataUrl).not.toHaveBeenCalled() expect(gitRoot).not.toHaveBeenCalled() }) it('uses the registered in-app picker in remote mode', async () => { const remoteSelect = vi.fn(async () => ['/remote/project']) $connection.set({ mode: 'remote' } as never) setDesktopFsRemotePicker({ selectPaths: remoteSelect }) await expect(selectDesktopPaths({ defaultPath: '/remote', directories: true, multiple: false })).resolves.toEqual([ '/remote/project' ]) expect(remoteSelect).toHaveBeenCalledWith({ defaultPath: '/remote', directories: true, multiple: false }) expect(selectPaths).not.toHaveBeenCalled() }) })