Initial local backup snapshot
This commit is contained in:
commit
acd9e14ba5
367 changed files with 118038 additions and 0 deletions
224
server/requestDetail.test.ts
Normal file
224
server/requestDetail.test.ts
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
import { describe, it, expect, vi } from 'vitest';
|
||||
|
||||
// Mock db module
|
||||
vi.mock('./db', () => ({
|
||||
getRequestById: vi.fn(),
|
||||
getAssociationByUserId: vi.fn(),
|
||||
getAssociationById: vi.fn(),
|
||||
getDocumentById: vi.fn(),
|
||||
getRequestHistoryByRequestId: vi.fn(),
|
||||
deleteRequest: vi.fn(),
|
||||
createAuditLog: vi.fn(),
|
||||
}));
|
||||
|
||||
import * as db from './db';
|
||||
|
||||
describe('Request Detail & Delete Logic', () => {
|
||||
describe('getById enrichment', () => {
|
||||
it('should return associationInfo when association exists', async () => {
|
||||
const mockAssociation = {
|
||||
id: 1,
|
||||
nomAssociation: 'Association Test',
|
||||
siret: '12345678901234',
|
||||
adresse: '10 rue de la Paix',
|
||||
codePostal: '97300',
|
||||
ville: 'Cayenne',
|
||||
telephone: '0594123456',
|
||||
emailContact: 'test@asso.fr',
|
||||
nomRepresentant: 'Jean Dupont',
|
||||
};
|
||||
|
||||
(db.getAssociationById as any).mockResolvedValue(mockAssociation);
|
||||
|
||||
const result = await db.getAssociationById(1);
|
||||
expect(result).toBeDefined();
|
||||
expect(result?.nomAssociation).toBe('Association Test');
|
||||
expect(result?.siret).toBe('12345678901234');
|
||||
expect(result?.telephone).toBe('0594123456');
|
||||
});
|
||||
|
||||
it('should return null when association does not exist', async () => {
|
||||
(db.getAssociationById as any).mockResolvedValue(null);
|
||||
|
||||
const result = await db.getAssociationById(999);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should resolve attached documents from documentsJoints JSON', async () => {
|
||||
const mockDoc1 = { id: 1, nom: 'Statuts', type: 'statuts', fileSize: 1024 };
|
||||
const mockDoc2 = { id: 2, nom: 'RIB', type: 'rib', fileSize: 2048 };
|
||||
|
||||
(db.getDocumentById as any)
|
||||
.mockResolvedValueOnce(mockDoc1)
|
||||
.mockResolvedValueOnce(mockDoc2);
|
||||
|
||||
const documentsJoints = JSON.stringify([1, 2]);
|
||||
const docIds = JSON.parse(documentsJoints) as number[];
|
||||
|
||||
const docs = await Promise.all(
|
||||
docIds.map(async (docId: number) => {
|
||||
const doc = await db.getDocumentById(docId);
|
||||
return doc || null;
|
||||
})
|
||||
);
|
||||
const attachedDocuments = docs.filter(Boolean);
|
||||
|
||||
expect(attachedDocuments).toHaveLength(2);
|
||||
expect(attachedDocuments[0]?.nom).toBe('Statuts');
|
||||
expect(attachedDocuments[1]?.nom).toBe('RIB');
|
||||
});
|
||||
|
||||
it('should handle empty documentsJoints gracefully', () => {
|
||||
const documentsJoints = null;
|
||||
let attachedDocuments: any[] = [];
|
||||
|
||||
if (documentsJoints) {
|
||||
try {
|
||||
const docIds = JSON.parse(documentsJoints) as number[];
|
||||
// would process here
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
expect(attachedDocuments).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should handle invalid JSON in documentsJoints', () => {
|
||||
const documentsJoints = 'not-json';
|
||||
let attachedDocuments: any[] = [];
|
||||
|
||||
if (documentsJoints) {
|
||||
try {
|
||||
const docIds = JSON.parse(documentsJoints) as number[];
|
||||
attachedDocuments = docIds as any[];
|
||||
} catch {
|
||||
// ignore parse errors
|
||||
}
|
||||
}
|
||||
|
||||
expect(attachedDocuments).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete request', () => {
|
||||
it('should allow deletion of a brouillon request by the owning association', async () => {
|
||||
const mockRequest = {
|
||||
id: 1,
|
||||
associationId: 10,
|
||||
status: 'brouillon',
|
||||
titre: 'Ma demande',
|
||||
type: 'subvention_fonctionnement',
|
||||
};
|
||||
const mockAssociation = { id: 10, userId: 5 };
|
||||
|
||||
(db.getRequestById as any).mockResolvedValue(mockRequest);
|
||||
(db.getAssociationByUserId as any).mockResolvedValue(mockAssociation);
|
||||
(db.deleteRequest as any).mockResolvedValue(undefined);
|
||||
|
||||
// Simulate the logic
|
||||
const request = await db.getRequestById(1);
|
||||
const association = await db.getAssociationByUserId(5);
|
||||
|
||||
expect(request).toBeDefined();
|
||||
expect(association).toBeDefined();
|
||||
expect(request!.associationId).toBe(association!.id);
|
||||
expect(request!.status).not.toBe('validee');
|
||||
expect(request!.status).not.toBe('refusee');
|
||||
|
||||
await db.deleteRequest(1);
|
||||
expect(db.deleteRequest).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it('should reject deletion of a validated request', async () => {
|
||||
const mockRequest = {
|
||||
id: 2,
|
||||
associationId: 10,
|
||||
status: 'validee',
|
||||
titre: 'Demande validée',
|
||||
type: 'subvention_projet',
|
||||
};
|
||||
|
||||
(db.getRequestById as any).mockResolvedValue(mockRequest);
|
||||
|
||||
const request = await db.getRequestById(2);
|
||||
expect(request!.status).toBe('validee');
|
||||
|
||||
// The router would throw a TRPCError here
|
||||
const canDelete = request!.status !== 'validee' && request!.status !== 'refusee';
|
||||
expect(canDelete).toBe(false);
|
||||
});
|
||||
|
||||
it('should reject deletion of a refused request', async () => {
|
||||
const mockRequest = {
|
||||
id: 3,
|
||||
associationId: 10,
|
||||
status: 'refusee',
|
||||
titre: 'Demande refusée',
|
||||
type: 'demande_salle',
|
||||
};
|
||||
|
||||
(db.getRequestById as any).mockResolvedValue(mockRequest);
|
||||
|
||||
const request = await db.getRequestById(3);
|
||||
const canDelete = request!.status !== 'validee' && request!.status !== 'refusee';
|
||||
expect(canDelete).toBe(false);
|
||||
});
|
||||
|
||||
it('should reject deletion by a non-owning association', async () => {
|
||||
const mockRequest = {
|
||||
id: 4,
|
||||
associationId: 10,
|
||||
status: 'soumise',
|
||||
titre: 'Demande autre asso',
|
||||
type: 'autre',
|
||||
};
|
||||
const mockAssociation = { id: 20, userId: 8 }; // Different association
|
||||
|
||||
(db.getRequestById as any).mockResolvedValue(mockRequest);
|
||||
(db.getAssociationByUserId as any).mockResolvedValue(mockAssociation);
|
||||
|
||||
const request = await db.getRequestById(4);
|
||||
const association = await db.getAssociationByUserId(8);
|
||||
|
||||
// Association ID mismatch
|
||||
expect(request!.associationId).not.toBe(association!.id);
|
||||
});
|
||||
|
||||
it('should allow deletion of a submitted request', async () => {
|
||||
const mockRequest = {
|
||||
id: 5,
|
||||
associationId: 10,
|
||||
status: 'soumise',
|
||||
titre: 'Demande soumise',
|
||||
type: 'subvention_fonctionnement',
|
||||
};
|
||||
|
||||
(db.getRequestById as any).mockResolvedValue(mockRequest);
|
||||
(db.deleteRequest as any).mockResolvedValue(undefined);
|
||||
|
||||
const request = await db.getRequestById(5);
|
||||
const canDelete = request!.status !== 'validee' && request!.status !== 'refusee';
|
||||
expect(canDelete).toBe(true);
|
||||
|
||||
await db.deleteRequest(5);
|
||||
expect(db.deleteRequest).toHaveBeenCalledWith(5);
|
||||
});
|
||||
|
||||
it('should allow deletion of a request in information_complementaire status', async () => {
|
||||
const mockRequest = {
|
||||
id: 6,
|
||||
associationId: 10,
|
||||
status: 'information_complementaire',
|
||||
titre: 'Demande info comp',
|
||||
type: 'agrement_sport',
|
||||
};
|
||||
|
||||
(db.getRequestById as any).mockResolvedValue(mockRequest);
|
||||
|
||||
const request = await db.getRequestById(6);
|
||||
const canDelete = request!.status !== 'validee' && request!.status !== 'refusee';
|
||||
expect(canDelete).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue