mirror of
https://github.com/EKKOLearnAI/hermes-web-ui.git
synced 2026-07-15 21:21:05 +00:00
66 lines
2.3 KiB
TypeScript
66 lines
2.3 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const {
|
|
mockCopyFile,
|
|
mockMkdir,
|
|
mockReadFile,
|
|
mockRename,
|
|
mockRm,
|
|
mockWriteFile,
|
|
} = vi.hoisted(() => ({
|
|
mockCopyFile: vi.fn(),
|
|
mockMkdir: vi.fn(),
|
|
mockReadFile: vi.fn(),
|
|
mockRename: vi.fn(),
|
|
mockRm: vi.fn(),
|
|
mockWriteFile: vi.fn(),
|
|
}))
|
|
|
|
vi.mock('fs/promises', () => ({
|
|
copyFile: mockCopyFile,
|
|
mkdir: mockMkdir,
|
|
readFile: mockReadFile,
|
|
rename: mockRename,
|
|
rm: mockRm,
|
|
writeFile: mockWriteFile,
|
|
}))
|
|
|
|
afterEach(() => {
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
describe('SafeFileStore backup fallback', () => {
|
|
it('uses a timestamped backup when the default backup cannot be overwritten', async () => {
|
|
mockCopyFile
|
|
.mockRejectedValueOnce(Object.assign(new Error('permission denied'), { code: 'EACCES' }))
|
|
.mockResolvedValueOnce(undefined)
|
|
mockMkdir.mockResolvedValue(undefined)
|
|
mockWriteFile.mockResolvedValue(undefined)
|
|
mockRename.mockResolvedValue(undefined)
|
|
|
|
const { SafeFileStore } = await import('../../packages/server/src/services/safe-file-store')
|
|
const store = new SafeFileStore()
|
|
|
|
await store.writeText('/tmp/config.yaml', 'model:\n default: new\n', { backup: true })
|
|
|
|
expect(mockCopyFile).toHaveBeenCalledTimes(2)
|
|
expect(mockCopyFile).toHaveBeenNthCalledWith(1, '/tmp/config.yaml', '/tmp/config.yaml.bak')
|
|
expect(mockCopyFile.mock.calls[1][0]).toBe('/tmp/config.yaml')
|
|
expect(mockCopyFile.mock.calls[1][1]).toMatch(/^\/tmp\/config\.yaml\.bak\.\d+\./)
|
|
expect(mockWriteFile).toHaveBeenCalledWith(expect.stringContaining('/tmp/config.yaml.tmp.'), 'model:\n default: new\n', 'utf-8')
|
|
expect(mockRename).toHaveBeenCalledWith(expect.stringContaining('/tmp/config.yaml.tmp.'), '/tmp/config.yaml')
|
|
})
|
|
|
|
it('preserves explicit backup path failures', async () => {
|
|
mockCopyFile.mockRejectedValueOnce(Object.assign(new Error('permission denied'), { code: 'EACCES' }))
|
|
mockMkdir.mockResolvedValue(undefined)
|
|
|
|
const { SafeFileStore } = await import('../../packages/server/src/services/safe-file-store')
|
|
const store = new SafeFileStore()
|
|
|
|
await expect(store.writeText('/tmp/config.yaml', 'new', { backup: true, backupPath: '/tmp/custom.bak' })).rejects.toThrow('permission denied')
|
|
expect(mockCopyFile).toHaveBeenCalledTimes(1)
|
|
expect(mockWriteFile).not.toHaveBeenCalled()
|
|
})
|
|
})
|