feat: finalize lease documents and IRL revisions

This commit is contained in:
nessar committed 2026-08-17 14:18:16 +02:00
1 parent f127c69a28
commit 1bf6a3449c
196 files changed
+20564 -666

No files matched your search

@@ -0,0 +1,123 @@
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');
});
});