import { TestBed } from '@angular/core/testing'; import { Subject, throwError } from 'rxjs'; import { vi } from 'vitest'; import { GuaranteeDeed, GuaranteeRequirement, LeaseFinalizationService, } from '../../services/lease-finalization.service'; import { GuaranteeDeedList } from './guarantee-deed-list'; describe('GuaranteeDeedList', () => { const requirement: GuaranteeRequirement = { guarantorId: 'guarantor-1', guarantorName: 'Alex Durand', tenantId: 'tenant-1', tenantName: 'Camille Martin', deed: null, }; const deed: GuaranteeDeed = { guarantorId: 'guarantor-1', tenantId: 'tenant-1', fileName: 'cautionnement.pdf', sha256: 'sha256', authorId: 'owner-1', uploadedAt: '2026-07-19T10:00:00Z', }; const uploadGuaranteeDeed = vi.fn(); beforeEach(() => { vi.clearAllMocks(); TestBed.configureTestingModule({ providers: [{ provide: LeaseFinalizationService, useValue: { uploadGuaranteeDeed } }], }); }); function createList(requirements = [requirement]) { const fixture = TestBed.createComponent(GuaranteeDeedList); fixture.componentRef.setInput('leaseId', 'lease-1'); fixture.componentRef.setInput('requirements', requirements); fixture.componentRef.setInput('simulatorUrl', 'https://www.service-public.fr/simulateur'); fixture.detectChanges(); return fixture; } it('shows each pair and an accessible official simulator link', () => { const fixture = createList(); const link: HTMLAnchorElement = fixture.nativeElement.querySelector('details a'); expect(fixture.nativeElement.textContent).toContain('Alex Durand garantit Camille Martin'); expect(link.href).toBe('https://www.service-public.fr/simulateur'); expect(link.target).toBe('_blank'); expect(link.rel).toContain('noopener'); expect(fixture.nativeElement.textContent).toContain('sans vérifier les signatures'); }); it('requires both a PDF and the attestation, with local pending feedback', () => { const response = new Subject(); uploadGuaranteeDeed.mockReturnValue(response); const fixture = createList(); const component = fixture.componentInstance; const file = new File(['deed'], 'cautionnement.pdf', { type: 'application/pdf' }); const uploaded = vi.fn(); component.deedUploaded.subscribe(uploaded); const button: HTMLButtonElement = fixture.nativeElement.querySelector('button'); expect(button.disabled).toBe(true); component.selectedFiles.set({ 'guarantor-1:tenant-1': file }); component.setAttestation(requirement, true); fixture.detectChanges(); button.click(); fixture.detectChanges(); expect(uploadGuaranteeDeed).toHaveBeenCalledWith('lease-1', file, 'guarantor-1', 'tenant-1'); expect(fixture.nativeElement.textContent).toContain('Téléversement…'); response.next(deed); response.complete(); expect(uploaded).toHaveBeenCalledWith({ guarantorId: 'guarantor-1', tenantId: 'tenant-1', deed, }); }); it('keeps an upload failure local to its pair', () => { uploadGuaranteeDeed.mockReturnValue(throwError(() => ({ error: { message: 'Acte refusé' } }))); const fixture = createList(); const component = fixture.componentInstance; component.selectedFiles.set({ 'guarantor-1:tenant-1': new File(['deed'], 'cautionnement.pdf', { type: 'application/pdf', }), }); component.setAttestation(requirement, true); component.upload(requirement); fixture.detectChanges(); expect(fixture.nativeElement.textContent).toContain('Acte refusé'); expect(fixture.nativeElement.querySelector('[role=alert]')).not.toBeNull(); }); it('renders an already uploaded deed without another upload form', () => { const fixture = createList([{ ...requirement, deed }]); expect(fixture.nativeElement.textContent).toContain('cautionnement.pdf'); expect(fixture.nativeElement.querySelector('input[type=file]')).toBeNull(); }); });