65 lines
2.2 KiB
TypeScript
65 lines
2.2 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const FILE = '00000000-0000-4000-8000-0000000000ff'
|
|
const mocks = vi.hoisted(() => ({
|
|
del: vi.fn(async () => {}),
|
|
log: vi.fn(async () => {}),
|
|
revalidatePath: vi.fn(),
|
|
loggerInfo: vi.fn(),
|
|
loggerRecordException: vi.fn(),
|
|
removed: [] as Array<{ id: string; url: string }>,
|
|
}))
|
|
|
|
const fakeDb = {
|
|
delete: () => ({
|
|
where: () => ({
|
|
returning: async () => mocks.removed,
|
|
}),
|
|
}),
|
|
}
|
|
|
|
vi.mock('next/cache', () => ({ revalidatePath: mocks.revalidatePath }))
|
|
vi.mock('@/shared/api', () => ({
|
|
db: () => fakeDb,
|
|
audit: () => ({ log: mocks.log }),
|
|
blob: () => ({ del: mocks.del }),
|
|
logger: () => ({ info: mocks.loggerInfo, recordException: mocks.loggerRecordException }),
|
|
}))
|
|
vi.mock('@/shared/lib/visitor-session', () => ({ ensureVisitor: async () => 'visitor-1' }))
|
|
|
|
import { deleteFile } from '@/features/delete-file/api/actions'
|
|
|
|
describe('deleteFile', () => {
|
|
beforeEach(() => {
|
|
mocks.del.mockClear()
|
|
mocks.log.mockClear()
|
|
mocks.revalidatePath.mockClear()
|
|
mocks.loggerInfo.mockClear()
|
|
mocks.loggerRecordException.mockClear()
|
|
mocks.removed.length = 0
|
|
})
|
|
|
|
it('removes the stored bytes and audits file.deleted once, and logs it', async () => {
|
|
mocks.removed.push({ id: FILE, url: 'https://blob.example.com/notes/n/a.png' })
|
|
await deleteFile(FILE)
|
|
|
|
expect(mocks.del).toHaveBeenCalledWith('https://blob.example.com/notes/n/a.png')
|
|
expect(mocks.log).toHaveBeenCalledTimes(1)
|
|
expect(mocks.log).toHaveBeenCalledWith('file.deleted', {
|
|
actor: { kind: 'human', id: 'visitor-1' },
|
|
target: { id: FILE },
|
|
})
|
|
expect(mocks.loggerInfo).toHaveBeenCalledTimes(1)
|
|
expect(mocks.loggerInfo).toHaveBeenCalledWith('file.deleted', { 'file.id': FILE, outcome: 'ok' })
|
|
expect(mocks.loggerRecordException).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('touches nothing when the visitor did not attach the file, and logs it denied', async () => {
|
|
await deleteFile(FILE)
|
|
expect(mocks.del).not.toHaveBeenCalled()
|
|
expect(mocks.log).not.toHaveBeenCalled()
|
|
expect(mocks.loggerInfo).toHaveBeenCalledWith('file.deleted', { 'file.id': FILE, outcome: 'denied' })
|
|
expect(mocks.loggerRecordException).not.toHaveBeenCalled()
|
|
})
|
|
})
|