Spaces:
Sleeping
Sleeping
| import { describe, it, expect, vi, beforeEach } from 'vitest'; | |
| import type { Request } from 'express'; | |
| // Mock the side-effect dependencies the wrapper reaches into directly. | |
| const { broadcast } = vi.hoisted(() => ({ broadcast: vi.fn() })); | |
| vi.mock('../../../src/websocket', () => ({ broadcast })); | |
| const { checkPermission } = vi.hoisted(() => ({ checkPermission: vi.fn(() => true) })); | |
| vi.mock('../../../src/services/permissions', () => ({ checkPermission })); | |
| const { svc } = vi.hoisted(() => ({ | |
| svc: { | |
| verifyTripAccess: vi.fn(), | |
| authenticateDownload: vi.fn(), | |
| resolveFilePath: vi.fn(), | |
| listFiles: vi.fn(), | |
| getFileById: vi.fn(), | |
| getDeletedFile: vi.fn(), | |
| createFile: vi.fn(), | |
| updateFile: vi.fn(), | |
| toggleStarred: vi.fn(), | |
| softDeleteFile: vi.fn(), | |
| restoreFile: vi.fn(), | |
| permanentDeleteFile: vi.fn(), | |
| emptyTrash: vi.fn(), | |
| createFileLink: vi.fn(), | |
| deleteFileLink: vi.fn(), | |
| getFileLinks: vi.fn(), | |
| }, | |
| })); | |
| vi.mock('../../../src/services/fileService', () => svc); | |
| import { FilesService } from '../../../src/nest/files/files.service'; | |
| import type { User } from '../../../src/types'; | |
| function service() { | |
| return new FilesService(); | |
| } | |
| beforeEach(() => vi.clearAllMocks()); | |
| describe('FilesService (thin wrapper around the legacy fileService)', () => { | |
| it('verifyTripAccess delegates to the legacy service', () => { | |
| svc.verifyTripAccess.mockReturnValue({ id: 5, user_id: 2 }); | |
| expect(service().verifyTripAccess('5', 2)).toEqual({ id: 5, user_id: 2 }); | |
| expect(svc.verifyTripAccess).toHaveBeenCalledWith('5', 2); | |
| }); | |
| it('can forwards the ownership flag when the user owns the trip', () => { | |
| checkPermission.mockReturnValue(true); | |
| const user = { id: 1, role: 'user' } as User; | |
| expect(service().can('file_edit', { user_id: 1 } as never, user)).toBe(true); | |
| expect(checkPermission).toHaveBeenCalledWith('file_edit', 'user', 1, 1, false); | |
| }); | |
| it('can marks the user as a guest when they do not own the trip', () => { | |
| checkPermission.mockReturnValue(false); | |
| const user = { id: 1, role: 'user' } as User; | |
| expect(service().can('file_upload', { user_id: 2 } as never, user)).toBe(false); | |
| expect(checkPermission).toHaveBeenCalledWith('file_upload', 'user', 2, 1, true); | |
| }); | |
| it('broadcast forwards to the websocket helper', () => { | |
| service().broadcast('5', 'file:created', { file: { id: 1 } }, 'sock'); | |
| expect(broadcast).toHaveBeenCalledWith('5', 'file:created', { file: { id: 1 } }, 'sock'); | |
| }); | |
| it('authenticateDownload / resolveFilePath delegate', () => { | |
| const req = { headers: {} } as Request; | |
| svc.authenticateDownload.mockReturnValue({ userId: 7 }); | |
| expect(service().authenticateDownload(req)).toEqual({ userId: 7 }); | |
| expect(svc.authenticateDownload).toHaveBeenCalledWith(req); | |
| svc.resolveFilePath.mockReturnValue({ resolved: '/a/b.pdf', safe: true }); | |
| expect(service().resolveFilePath('b.pdf')).toEqual({ resolved: '/a/b.pdf', safe: true }); | |
| expect(svc.resolveFilePath).toHaveBeenCalledWith('b.pdf'); | |
| }); | |
| it('the read helpers delegate', () => { | |
| svc.listFiles.mockReturnValue([{ id: 1 }]); | |
| expect(service().listFiles('5', true)).toEqual([{ id: 1 }]); | |
| expect(svc.listFiles).toHaveBeenCalledWith('5', true); | |
| svc.getFileById.mockReturnValue({ id: 9 }); | |
| expect(service().getFileById('9', '5')).toEqual({ id: 9 }); | |
| expect(svc.getFileById).toHaveBeenCalledWith('9', '5'); | |
| svc.getDeletedFile.mockReturnValue({ id: 9 }); | |
| expect(service().getDeletedFile('9', '5')).toEqual({ id: 9 }); | |
| expect(svc.getDeletedFile).toHaveBeenCalledWith('9', '5'); | |
| svc.getFileLinks.mockReturnValue([{ id: 1 }]); | |
| expect(service().getFileLinks('9')).toEqual([{ id: 1 }]); | |
| expect(svc.getFileLinks).toHaveBeenCalledWith('9'); | |
| }); | |
| it('the mutating helpers delegate', () => { | |
| const file = { filename: 'a.pdf' } as Express.Multer.File; | |
| svc.createFile.mockReturnValue({ id: 9 }); | |
| expect(service().createFile('5', file, 1, { description: 'd' })).toEqual({ id: 9 }); | |
| expect(svc.createFile).toHaveBeenCalledWith('5', file, 1, { description: 'd' }); | |
| svc.updateFile.mockReturnValue({ id: 9 }); | |
| const current = { id: 9 } as never; | |
| expect(service().updateFile('9', current, { description: 'x' })).toEqual({ id: 9 }); | |
| expect(svc.updateFile).toHaveBeenCalledWith('9', current, { description: 'x' }); | |
| svc.toggleStarred.mockReturnValue({ id: 9, starred: 1 }); | |
| expect(service().toggleStarred('9', 0)).toEqual({ id: 9, starred: 1 }); | |
| expect(svc.toggleStarred).toHaveBeenCalledWith('9', 0); | |
| service().softDeleteFile('9'); | |
| expect(svc.softDeleteFile).toHaveBeenCalledWith('9'); | |
| svc.restoreFile.mockReturnValue({ id: 9 }); | |
| expect(service().restoreFile('9')).toEqual({ id: 9 }); | |
| expect(svc.restoreFile).toHaveBeenCalledWith('9'); | |
| const trashed = { id: 9 } as never; | |
| service().permanentDeleteFile(trashed); | |
| expect(svc.permanentDeleteFile).toHaveBeenCalledWith(trashed); | |
| svc.emptyTrash.mockReturnValue(3); | |
| expect(service().emptyTrash('5')).toBe(3); | |
| expect(svc.emptyTrash).toHaveBeenCalledWith('5'); | |
| svc.createFileLink.mockReturnValue([{ id: 1 }]); | |
| expect(service().createFileLink('9', { reservation_id: 2 })).toEqual([{ id: 1 }]); | |
| expect(svc.createFileLink).toHaveBeenCalledWith('9', { reservation_id: 2 }); | |
| service().deleteFileLink('3', '9'); | |
| expect(svc.deleteFileLink).toHaveBeenCalledWith('3', '9'); | |
| }); | |
| }); | |