import { ComponentFixture, TestBed } from '@angular/core/testing'; import { provideRouter } from '@angular/router'; import { of, throwError } from 'rxjs'; import { MaterialeProposta } from '../catalogo/materiali-api.service'; import { MaterialiModerazioneApiService } from './materiali-moderazione-api.service'; import { Moderazione } from './moderazione'; describe('Moderazione', () => { let component: Moderazione; let fixture: ComponentFixture; let moderazioneApi: { getProposte: ReturnType; decidiProposta: ReturnType }; const proposte: MaterialeProposta[] = [ { id: 'prop-1', nome: 'Fune da bucato', categoria: 'Campeggio', unitaMisura: 'pz', stato: 'proposto', propostoDaOrgId: 'org-1', creatoIl: '2026-01-01T00:00:00.000Z' }, { id: 'prop-2', nome: 'Piccone', categoria: 'Attrezzatura', unitaMisura: 'pz', stato: 'proposto', propostoDaOrgId: 'org-2', creatoIl: '2026-01-02T00:00:00.000Z' } ]; async function setup(): Promise { await TestBed.configureTestingModule({ imports: [Moderazione], providers: [provideRouter([]), { provide: MaterialiModerazioneApiService, useValue: moderazioneApi }] }).compileComponents(); fixture = TestBed.createComponent(Moderazione); component = fixture.componentInstance; fixture.detectChanges(); await fixture.whenStable(); fixture.detectChanges(); } beforeEach(() => { moderazioneApi = { getProposte: vi.fn().mockReturnValue(of(proposte)), decidiProposta: vi.fn() }; }); it('mostra la lista delle proposte in attesa', async () => { await setup(); fixture.detectChanges(); expect(component.loading()).toBe(false); expect(component.proposte()).toEqual(proposte); const compiled = fixture.nativeElement as HTMLElement; const righe = compiled.querySelectorAll('.moderazione__tabella tbody tr'); expect(righe.length).toBe(2); expect(righe[0].textContent).toContain('Fune da bucato'); }); it('mostra un messaggio se non ci sono proposte in attesa', async () => { moderazioneApi.getProposte.mockReturnValue(of([])); await setup(); const compiled = fixture.nativeElement as HTMLElement; expect(compiled.textContent).toContain('Nessuna proposta in attesa'); }); it('mostra un messaggio di errore se il caricamento fallisce', async () => { moderazioneApi.getProposte.mockReturnValue(throwError(() => new Error('network error'))); await setup(); expect(component.loadError()).toBe('Impossibile caricare le proposte in attesa. Riprova più tardi.'); }); describe('approvazione e rifiuto', () => { beforeEach(async () => { await setup(); }); it('approva una proposta e la rimuove dalla lista', async () => { const propostaApprovata: MaterialeProposta = { ...proposte[0], stato: 'approvato' }; moderazioneApi.decidiProposta.mockReturnValue(of(propostaApprovata)); await component.decidi(proposte[0], 'approvato'); expect(moderazioneApi.decidiProposta).toHaveBeenCalledWith('prop-1', 'approvato'); expect(component.proposte().map((p) => p.id)).toEqual(['prop-2']); }); it('rifiuta una proposta e la rimuove dalla lista', async () => { const propostaRifiutata: MaterialeProposta = { ...proposte[1], stato: 'rifiutato' }; moderazioneApi.decidiProposta.mockReturnValue(of(propostaRifiutata)); await component.decidi(proposte[1], 'rifiutato'); expect(moderazioneApi.decidiProposta).toHaveBeenCalledWith('prop-2', 'rifiutato'); expect(component.proposte().map((p) => p.id)).toEqual(['prop-1']); }); it('mostra un messaggio di errore sulla proposta interessata se la decisione fallisce', async () => { moderazioneApi.decidiProposta.mockReturnValue(throwError(() => new Error('server error'))); await component.decidi(proposte[0], 'approvato'); expect(component.decisioneErroreId()).toBe('prop-1'); expect(component.proposte().map((p) => p.id)).toEqual(['prop-1', 'prop-2']); fixture.detectChanges(); const compiled = fixture.nativeElement as HTMLElement; expect(compiled.textContent).toContain('Impossibile registrare la decisione'); }); }); });