From 7576b5a68caba9b4b0331a2b26ddfa573c3953a6 Mon Sep 17 00:00:00 2001 From: Luc SORIGNET Date: Sun, 15 Mar 2026 12:09:18 +0100 Subject: [PATCH] test(frontend): ajout tests unitaires Jest composants frais [#NEWTS-9] --- Front-End/src/test/FeeTypeSection.test.js | 149 ++++++++++++++++++++++ Front-End/src/test/FeesManagement.test.js | 145 +++++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 Front-End/src/test/FeeTypeSection.test.js create mode 100644 Front-End/src/test/FeesManagement.test.js diff --git a/Front-End/src/test/FeeTypeSection.test.js b/Front-End/src/test/FeeTypeSection.test.js new file mode 100644 index 0000000..0fde419 --- /dev/null +++ b/Front-End/src/test/FeeTypeSection.test.js @@ -0,0 +1,149 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import FeeTypeSection from '@/components/Structure/Tarification/FeeTypeSection'; + +// Mock du contexte établissement +jest.mock('@/context/EstablishmentContext', () => ({ + useEstablishment: () => ({ selectedEstablishmentId: 1 }), +})); + +// Mock des sous-composants pour isoler FeeTypeSection +jest.mock( + '@/components/Structure/Tarification/FeesSection', + () => + function MockFeesSection({ type }) { + return ( +
+ FeesSection type={type} +
+ ); + } +); + +jest.mock( + '@/components/Structure/Tarification/DiscountsSection', + () => + function MockDiscountsSection({ type }) { + return ( +
+ DiscountsSection type={type} +
+ ); + } +); + +jest.mock( + '@/components/PaymentPlanSelector', + () => + function MockPaymentPlanSelector({ type }) { + return ( +
+ PaymentPlanSelector type={type} +
+ ); + } +); + +jest.mock( + '@/components/PaymentModeSelector', + () => + function MockPaymentModeSelector({ type }) { + return ( +
+ PaymentModeSelector type={type} +
+ ); + } +); + +jest.mock('@/utils/Url', () => ({ + BE_SCHOOL_FEES_URL: '/api/fees', + BE_SCHOOL_DISCOUNTS_URL: '/api/discounts', + BE_SCHOOL_PAYMENT_PLANS_URL: '/api/payment-plans', + BE_SCHOOL_PAYMENT_MODES_URL: '/api/payment-modes', +})); + +const defaultProps = { + title: "Frais d'inscription", + fees: [], + setFees: jest.fn(), + discounts: [], + setDiscounts: jest.fn(), + paymentPlans: [], + setPaymentPlans: jest.fn(), + paymentModes: [], + setPaymentModes: jest.fn(), + type: 0, + handleCreate: jest.fn(), + handleEdit: jest.fn(), + handleDelete: jest.fn(), + onDiscountDelete: jest.fn(), +}; + +describe('FeeTypeSection - type inscription (type=0)', () => { + it('affiche le titre passé en props', () => { + render(); + expect(screen.getByText("Frais d'inscription")).toBeInTheDocument(); + }); + + it('rend le composant FeesSection avec le bon type', () => { + render(); + expect(screen.getByTestId('fees-section-type-0')).toBeInTheDocument(); + }); + + it('rend le composant DiscountsSection avec le bon type', () => { + render(); + expect(screen.getByTestId('discounts-section-type-0')).toBeInTheDocument(); + }); + + it('rend le composant PaymentPlanSelector avec le bon type', () => { + render(); + expect(screen.getByTestId('payment-plan-type-0')).toBeInTheDocument(); + }); + + it('rend le composant PaymentModeSelector avec le bon type', () => { + render(); + expect(screen.getByTestId('payment-mode-type-0')).toBeInTheDocument(); + }); +}); + +describe('FeeTypeSection - type scolarité (type=1)', () => { + const tuitionProps = { + ...defaultProps, + title: 'Frais de scolarité', + type: 1, + }; + + it('affiche le titre "Frais de scolarité"', () => { + render(); + expect(screen.getByText('Frais de scolarité')).toBeInTheDocument(); + }); + + it('rend tous les sous-composants avec type=1', () => { + render(); + expect(screen.getByTestId('fees-section-type-1')).toBeInTheDocument(); + expect(screen.getByTestId('discounts-section-type-1')).toBeInTheDocument(); + expect(screen.getByTestId('payment-plan-type-1')).toBeInTheDocument(); + expect(screen.getByTestId('payment-mode-type-1')).toBeInTheDocument(); + }); +}); + +describe('FeeTypeSection - transmission des handlers', () => { + it('passe les fonctions handleCreate, handleEdit, handleDelete aux sous-composants', () => { + const handleCreate = jest.fn(); + const handleEdit = jest.fn(); + const handleDelete = jest.fn(); + + // On vérifie que le composant se rend sans erreur avec les handlers + expect(() => + render( + + ) + ).not.toThrow(); + }); +}); diff --git a/Front-End/src/test/FeesManagement.test.js b/Front-End/src/test/FeesManagement.test.js new file mode 100644 index 0000000..9054d05 --- /dev/null +++ b/Front-End/src/test/FeesManagement.test.js @@ -0,0 +1,145 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import FeesManagement from '@/components/Structure/Tarification/FeesManagement'; + +jest.mock('@/context/EstablishmentContext', () => ({ + useEstablishment: () => ({ selectedEstablishmentId: 1 }), +})); + +jest.mock('@/utils/Url', () => ({ + BE_SCHOOL_FEES_URL: '/api/fees', + BE_SCHOOL_DISCOUNTS_URL: '/api/discounts', + BE_SCHOOL_PAYMENT_PLANS_URL: '/api/payment-plans', + BE_SCHOOL_PAYMENT_MODES_URL: '/api/payment-modes', +})); + +jest.mock('@/utils/logger', () => ({ error: jest.fn() })); + +jest.mock( + '@/components/Structure/Tarification/FeesSection', + () => + function MockFeesSection({ fees, unified }) { + return ( +
+ {fees.map((f) => ( + {f.name} + ))} +
+ ); + } +); + +jest.mock( + '@/components/Structure/Tarification/DiscountsSection', + () => + function MockDiscountsSection({ discounts, unified }) { + return ( +
+ {discounts.map((d) => ( + {d.name} + ))} +
+ ); + } +); + +jest.mock( + '@/components/PaymentPlanSelector', + () => + function MockPaymentPlanSelector({ allPaymentPlans }) { + return ( +
+ {(allPaymentPlans ?? []).length} plans +
+ ); + } +); + +jest.mock( + '@/components/PaymentModeSelector', + () => + function MockPaymentModeSelector({ allPaymentModes }) { + return ( +
+ {(allPaymentModes ?? []).length} modes +
+ ); + } +); + +const defaultProps = { + registrationFees: [], + setRegistrationFees: jest.fn(), + tuitionFees: [], + setTuitionFees: jest.fn(), + registrationDiscounts: [], + setRegistrationDiscounts: jest.fn(), + tuitionDiscounts: [], + setTuitionDiscounts: jest.fn(), + registrationPaymentPlans: [], + setRegistrationPaymentPlans: jest.fn(), + tuitionPaymentPlans: [], + setTuitionPaymentPlans: jest.fn(), + registrationPaymentModes: [], + setRegistrationPaymentModes: jest.fn(), + tuitionPaymentModes: [], + setTuitionPaymentModes: jest.fn(), + handleCreate: jest.fn(), + handleEdit: jest.fn(), + handleDelete: jest.fn(), +}; + +describe('FeesManagement - vue unifiée', () => { + it('affiche la section des frais en mode unifié', () => { + render(); + const section = screen.getByTestId('fees-section'); + expect(section).toBeInTheDocument(); + expect(section).toHaveAttribute('data-unified', 'true'); + }); + + it('affiche la section des réductions en mode unifié', () => { + render(); + const section = screen.getByTestId('discounts-section'); + expect(section).toBeInTheDocument(); + expect(section).toHaveAttribute('data-unified', 'true'); + }); + + it('affiche le sélecteur de plans de paiement', () => { + render(); + expect(screen.getByTestId('payment-plan-selector')).toBeInTheDocument(); + }); + + it('affiche le sélecteur de modes de paiement', () => { + render(); + expect(screen.getByTestId('payment-mode-selector')).toBeInTheDocument(); + }); + + it('fusionne les frais inscription et scolarité en une seule liste', () => { + render( + + ); + expect(screen.getByText('Inscription A')).toBeInTheDocument(); + expect(screen.getByText('Scolarité B')).toBeInTheDocument(); + }); + + it('fusionne les plans de paiement inscription et scolarité', () => { + render( + + ); + expect(screen.getByText('2 plans')).toBeInTheDocument(); + }); +});