231 lines
7.7 KiB
TypeScript
231 lines
7.7 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
|
// Mock db module
|
|
vi.mock('./db', () => ({
|
|
getRequestById: vi.fn(),
|
|
updateRequestSalles: vi.fn(),
|
|
createRequestHistory: vi.fn(),
|
|
getAssociationById: vi.fn(),
|
|
getApprovedReservations: vi.fn(),
|
|
}));
|
|
|
|
// Mock notification
|
|
vi.mock('./_core/notification', () => ({
|
|
notifyOwner: vi.fn().mockResolvedValue(true),
|
|
}));
|
|
|
|
import * as db from './db';
|
|
import { notifyOwner } from './_core/notification';
|
|
|
|
describe('Calendrier des réservations - Backend', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe('getApprovedReservations', () => {
|
|
it('should return approved reservations with association info', async () => {
|
|
const mockReservations = [
|
|
{
|
|
id: 1,
|
|
associationId: 10,
|
|
type: 'demande_salle',
|
|
titre: 'Réservation Salle TOUCAN',
|
|
status: 'validee',
|
|
formData: JSON.stringify({
|
|
sallesSelectionnees: ['Salle TOUCAN'],
|
|
dateReservation: '2026-04-15',
|
|
heureDebut: '09:00',
|
|
heureFin: '17:00',
|
|
motifReservation: 'AG annuelle',
|
|
}),
|
|
associationName: 'Association Test',
|
|
associationEmail: 'test@asso.fr',
|
|
createdAt: new Date('2026-03-01'),
|
|
},
|
|
{
|
|
id: 2,
|
|
associationId: 11,
|
|
type: 'demande_salle',
|
|
titre: 'Réservation DOJO',
|
|
status: 'validee',
|
|
formData: JSON.stringify({
|
|
sallesSelectionnees: ['DOJO'],
|
|
dateReservation: '2026-04-20',
|
|
heureDebut: '18:00',
|
|
heureFin: '20:00',
|
|
motifReservation: 'Entraînement',
|
|
}),
|
|
associationName: 'Club Judo',
|
|
associationEmail: 'judo@club.fr',
|
|
createdAt: new Date('2026-03-05'),
|
|
},
|
|
];
|
|
|
|
vi.mocked(db.getApprovedReservations).mockResolvedValue(mockReservations as any);
|
|
|
|
const result = await db.getApprovedReservations();
|
|
expect(result).toHaveLength(2);
|
|
expect(result[0].associationName).toBe('Association Test');
|
|
expect(result[1].associationName).toBe('Club Judo');
|
|
});
|
|
|
|
it('should return empty array when no approved reservations', async () => {
|
|
vi.mocked(db.getApprovedReservations).mockResolvedValue([]);
|
|
const result = await db.getApprovedReservations();
|
|
expect(result).toHaveLength(0);
|
|
});
|
|
});
|
|
|
|
describe('changeSalles - logic simulation', () => {
|
|
it('should update salles in formData correctly', async () => {
|
|
const existingRequest = {
|
|
id: 1,
|
|
type: 'demande_salle',
|
|
associationId: 10,
|
|
status: 'validee',
|
|
formData: JSON.stringify({
|
|
sallesSelectionnees: ['Salle TOUCAN'],
|
|
sallesIds: ['salle_toucan'],
|
|
dateReservation: '2026-04-15',
|
|
heureDebut: '09:00',
|
|
heureFin: '17:00',
|
|
}),
|
|
};
|
|
|
|
vi.mocked(db.getRequestById).mockResolvedValue(existingRequest as any);
|
|
vi.mocked(db.updateRequestSalles).mockResolvedValue(undefined);
|
|
vi.mocked(db.createRequestHistory).mockResolvedValue(undefined as any);
|
|
vi.mocked(db.getAssociationById).mockResolvedValue({
|
|
id: 10,
|
|
nomAssociation: 'Association Test',
|
|
emailContact: 'test@asso.fr',
|
|
} as any);
|
|
|
|
// Simulate the changeSalles logic
|
|
const request = await db.getRequestById(1);
|
|
expect(request).toBeDefined();
|
|
expect(request!.type).toBe('demande_salle');
|
|
|
|
const formData = JSON.parse(request!.formData!);
|
|
const anciennesSalles = formData.sallesSelectionnees;
|
|
|
|
// Update salles
|
|
formData.sallesSelectionnees = ['Salle IBIS', 'Salle PELICAN'];
|
|
formData.sallesIds = ['salle_ibis', 'salle_pelican'];
|
|
|
|
// Add change history
|
|
formData.historiqueChangementsSalles = [{
|
|
date: new Date().toISOString(),
|
|
anciennesSalles,
|
|
nouvellesSalles: ['Salle IBIS', 'Salle PELICAN'],
|
|
raison: 'Besoin d\'une salle plus grande',
|
|
parAdmin: 1,
|
|
}];
|
|
|
|
await db.updateRequestSalles(1, JSON.stringify(formData));
|
|
|
|
expect(db.updateRequestSalles).toHaveBeenCalledWith(
|
|
1,
|
|
expect.stringContaining('Salle IBIS')
|
|
);
|
|
|
|
// Verify the updated formData
|
|
const updatedFormData = JSON.parse(
|
|
vi.mocked(db.updateRequestSalles).mock.calls[0][1]
|
|
);
|
|
expect(updatedFormData.sallesSelectionnees).toEqual(['Salle IBIS', 'Salle PELICAN']);
|
|
expect(updatedFormData.sallesIds).toEqual(['salle_ibis', 'salle_pelican']);
|
|
expect(updatedFormData.historiqueChangementsSalles).toHaveLength(1);
|
|
expect(updatedFormData.historiqueChangementsSalles[0].anciennesSalles).toEqual(['Salle TOUCAN']);
|
|
expect(updatedFormData.historiqueChangementsSalles[0].raison).toBe('Besoin d\'une salle plus grande');
|
|
});
|
|
|
|
it('should create request history entry for salle change', async () => {
|
|
vi.mocked(db.createRequestHistory).mockResolvedValue(undefined as any);
|
|
|
|
await db.createRequestHistory({
|
|
requestId: 1,
|
|
action: 'changement_salle',
|
|
ancienStatut: 'validee',
|
|
nouveauStatut: 'validee',
|
|
userId: 1,
|
|
commentaire: 'Changement de salle(s) : Salle TOUCAN → Salle IBIS. Raison : Besoin d\'une salle plus grande',
|
|
});
|
|
|
|
expect(db.createRequestHistory).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
requestId: 1,
|
|
action: 'changement_salle',
|
|
commentaire: expect.stringContaining('Salle TOUCAN'),
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should reject change for non-salle requests', async () => {
|
|
const nonSalleRequest = {
|
|
id: 2,
|
|
type: 'subvention_fonctionnement',
|
|
associationId: 10,
|
|
status: 'validee',
|
|
formData: '{}',
|
|
};
|
|
|
|
vi.mocked(db.getRequestById).mockResolvedValue(nonSalleRequest as any);
|
|
|
|
const request = await db.getRequestById(2);
|
|
expect(request!.type).not.toBe('demande_salle');
|
|
// In the actual procedure, this would throw a TRPCError
|
|
});
|
|
|
|
it('should send notification to association on salle change', async () => {
|
|
vi.mocked(db.getAssociationById).mockResolvedValue({
|
|
id: 10,
|
|
nomAssociation: 'Association Test',
|
|
emailContact: 'test@asso.fr',
|
|
} as any);
|
|
|
|
const association = await db.getAssociationById(10);
|
|
expect(association).toBeDefined();
|
|
|
|
await notifyOwner({
|
|
title: 'Changement de salle pour votre réservation',
|
|
content: `Bonjour ${association!.nomAssociation}, votre salle a été modifiée.`,
|
|
});
|
|
|
|
expect(notifyOwner).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
title: 'Changement de salle pour votre réservation',
|
|
content: expect.stringContaining('Association Test'),
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should preserve change history across multiple changes', () => {
|
|
const formData = {
|
|
sallesSelectionnees: ['Salle PELICAN'],
|
|
sallesIds: ['salle_pelican'],
|
|
historiqueChangementsSalles: [
|
|
{
|
|
date: '2026-03-10T10:00:00Z',
|
|
anciennesSalles: ['Salle TOUCAN'],
|
|
nouvellesSalles: ['Salle IBIS'],
|
|
raison: 'Premier changement',
|
|
parAdmin: 1,
|
|
},
|
|
{
|
|
date: '2026-03-11T14:00:00Z',
|
|
anciennesSalles: ['Salle IBIS'],
|
|
nouvellesSalles: ['Salle PELICAN'],
|
|
raison: 'Deuxième changement',
|
|
parAdmin: 1,
|
|
},
|
|
],
|
|
};
|
|
|
|
expect(formData.historiqueChangementsSalles).toHaveLength(2);
|
|
expect(formData.historiqueChangementsSalles[0].anciennesSalles).toEqual(['Salle TOUCAN']);
|
|
expect(formData.historiqueChangementsSalles[1].nouvellesSalles).toEqual(['Salle PELICAN']);
|
|
expect(formData.sallesSelectionnees).toEqual(['Salle PELICAN']);
|
|
});
|
|
});
|
|
});
|