import { TestBed } from '@angular/core/testing'; import { vi } from 'vitest'; import { LeaseRevisionMetadata } from '../../services/lease.service'; import { LeaseFinalizationForm } from './lease-finalization-form'; describe('LeaseFinalizationForm', () => { const revision: LeaseRevisionMetadata = { number: 4, templateVersion: '2026.10', sourceFingerprint: 'source', sha256: 'sha256', generatedAt: '2026-07-19T10:00:00Z', authorId: 'owner-1', annexes: [], warningCodes: [], warnings: [], }; function createForm(warningCodes: string[] = []) { const fixture = TestBed.createComponent(LeaseFinalizationForm); fixture.componentRef.setInput('revision', revision); fixture.componentRef.setInput('warningCodes', warningCodes); fixture.componentRef.setInput( 'warnings', warningCodes.map((code) => ({ code, ruleVersion: '2026-07-01' })), ); fixture.detectChanges(); return fixture; } it('emits the exact civil date string and confirmations', () => { const fixture = createForm([ 'SECURITY_DEPOSIT_ABOVE_TWO_MONTHS', 'IRL_REVISION_WITH_F_OR_G_DPE', 'FUTURE_WARNING', ]); const component = fixture.componentInstance; const file = new File(['lease'], 'bail-signe.pdf', { type: 'application/pdf' }); const requested = vi.fn(); component.finalizationRequested.subscribe(requested); component.signedLease.set(file); component.lastSignatureDate.set('2026-07-19'); component.allPartiesSigned.set(true); component.revisionMatches.set(true); component.setWarning('SECURITY_DEPOSIT_ABOVE_TWO_MONTHS', true); component.setWarning('IRL_REVISION_WITH_F_OR_G_DPE', true); component.setWarning('FUTURE_WARNING', true); component.submit(); expect(requested).toHaveBeenCalledWith({ signedLease: file, revisionNumber: 4, lastSignatureDate: '2026-07-19', allPartiesSigned: true, revisionMatches: true, confirmedWarningCodes: [ 'SECURITY_DEPOSIT_ABOVE_TWO_MONTHS', 'IRL_REVISION_WITH_F_OR_G_DPE', 'FUTURE_WARNING', ], }); }); it('uses actionable French warning labels without exposing raw codes', () => { const fixture = createForm([ 'SECURITY_DEPOSIT_ABOVE_TWO_MONTHS', 'IRL_REVISION_WITH_F_OR_G_DPE', 'FUTURE_WARNING', ]); const text = fixture.nativeElement.textContent; expect(text).toContain('dépasse deux mois de loyer hors charges'); expect(text).toContain('confirme forcer ce montant'); expect(text).toContain('classé F ou G'); expect(text).toContain('maintenir la clause de révision IRL'); expect(text).toContain('avertissement légal signalé'); expect(text).not.toContain('SECURITY_DEPOSIT_ABOVE_TWO_MONTHS'); expect(text).not.toContain('FUTURE_WARNING'); expect(text).not.toContain('IRL_REVISION_WITH_F_OR_G_DPE'); expect(text).toContain('Version de règle : 2026-07-01'); }); it('explains every document warning precisely in French', () => { const warningCodes = [ 'DPE_MISSING', 'DPE_EXPIRED', 'DIAGNOSTIC_EXPIRED', 'CO_OWNERSHIP_RULES_EXTRACT_MISSING', 'PRIOR_RENTAL_AUTHORIZATION_MISSING', ]; const fixture = createForm(warningCodes); const text = fixture.nativeElement.textContent; expect(text).toContain('DPE est absent du dossier'); expect(text).toContain('DPE présent dans le dossier est expiré'); expect(text).toContain('diagnostic autre que le DPE est expiré'); expect(text).toContain('extrait du règlement de copropriété manque'); expect(text).toContain('autorisation préalable de mise en location manque'); for (const code of warningCodes) expect(text).not.toContain(code); }); it('blocks an incomplete submission with an actionable error', () => { const fixture = createForm(['SECURITY_DEPOSIT_ABOVE_TWO_MONTHS']); const requested = vi.fn(); fixture.componentInstance.finalizationRequested.subscribe(requested); fixture.componentInstance.submit(); fixture.detectChanges(); expect(requested).not.toHaveBeenCalled(); expect(fixture.nativeElement.textContent).toContain('Sélectionnez le bail signé'); }); it('blocks finalization while a required guarantee deed is missing', () => { const fixture = createForm(); fixture.componentRef.setInput('guaranteesComplete', false); fixture.detectChanges(); expect(fixture.nativeElement.querySelector('button[type=submit]').disabled).toBe(true); expect(fixture.nativeElement.textContent).toContain('Téléversez tous les actes'); }); });