mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-19 13:21:46 +00:00
7266ad99ae
* fix(server): set oxc:false in vitest so the SWC transform survives the Vite 8 bump * fix(server): switch coverage to the istanbul provider (v8 under-reports branches on Vite 8 + Vitest 4) * test(nest): cover controller/service branches to clear the 80% coverage gate
135 lines
5.4 KiB
TypeScript
135 lines
5.4 KiB
TypeScript
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');
|
|
});
|
|
});
|