import { TestBed } from '@angular/core/testing'; import { ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, provideRouter, Router } from '@angular/router'; import Keycloak from 'keycloak-js'; import { of, throwError } from 'rxjs'; import { EventiApiService, EventoDettaglioView } from '../eventi-api.service'; import { requireBrancaAccessEventoGuard, requireCreaEventoGuard } from './require-branca-access.guard'; const state = {} as RouterStateSnapshot; const eventoLupetti: EventoDettaglioView = { id: 'evento-1', orgId: 'org-1', brancaId: 'Lupetti', parentId: null, titolo: 'Campo estivo', descrizione: null, dataInizio: '2026-07-10T08:00:00.000Z', dataFine: '2026-07-10T18:00:00.000Z', tipo: 'campo', location: null, creatoDa: 'user-1', creatoIl: '2026-06-01T00:00:00.000Z', figli: [], risorseCollegate: [] }; function setup(options: { roles?: string[]; groups?: string[]; getEvento?: ReturnType; }): void { const keycloakMock = { tokenParsed: { realm_access: { roles: options.roles ?? [] }, groups: options.groups ?? [] } }; TestBed.configureTestingModule({ providers: [ provideRouter([]), { provide: Keycloak, useValue: keycloakMock }, { provide: EventiApiService, useValue: { getEvento: options.getEvento ?? vi.fn().mockReturnValue(of(eventoLupetti)) } } ] }); } describe('requireCreaEventoGuard', () => { const route = {} as ActivatedRouteSnapshot; it('lascia proseguire capo-gruppo', () => { setup({ roles: ['capo-gruppo'] }); const result = TestBed.runInInjectionContext(() => requireCreaEventoGuard(route, state)); expect(result).toBe(true); }); it('lascia proseguire capo-unita con almeno una branca', () => { setup({ roles: ['capo-unita'], groups: ['/Lupetti'] }); const result = TestBed.runInInjectionContext(() => requireCreaEventoGuard(route, state)); expect(result).toBe(true); }); it('reindirizza alla vista mensile per censito', () => { setup({ roles: ['censito'], groups: ['/Lupetti'] }); const result = TestBed.runInInjectionContext(() => requireCreaEventoGuard(route, state)); const router = TestBed.inject(Router); expect((result as UrlTree).toString()).toBe(router.parseUrl('/vista-mensile').toString()); }); it('reindirizza alla vista mensile per capo-unita senza nessuna branca', () => { setup({ roles: ['capo-unita'], groups: [] }); const result = TestBed.runInInjectionContext(() => requireCreaEventoGuard(route, state)); const router = TestBed.inject(Router); expect((result as UrlTree).toString()).toBe(router.parseUrl('/vista-mensile').toString()); }); it('lascia proseguire capo con almeno una branca (stessi permessi di capo-unita)', () => { setup({ roles: ['capo'], groups: ['/Lupetti'] }); const result = TestBed.runInInjectionContext(() => requireCreaEventoGuard(route, state)); expect(result).toBe(true); }); }); describe('requireBrancaAccessEventoGuard', () => { function buildRoute(id: string | null): ActivatedRouteSnapshot { return { paramMap: { get: () => id } } as unknown as ActivatedRouteSnapshot; } it('lascia proseguire capo-gruppo su qualunque branca', async () => { setup({ roles: ['capo-gruppo'] }); const result = await TestBed.runInInjectionContext(() => requireBrancaAccessEventoGuard(buildRoute('evento-1'), state)); expect(result).toBe(true); }); it('lascia proseguire capo-unita sulla branca dell\'evento', async () => { setup({ roles: ['capo-unita'], groups: ['/Lupetti'] }); const result = await TestBed.runInInjectionContext(() => requireBrancaAccessEventoGuard(buildRoute('evento-1'), state)); expect(result).toBe(true); }); it('reindirizza al dettaglio evento per capo-unita di un\'altra branca', async () => { setup({ roles: ['capo-unita'], groups: ['/Esploratori'] }); const result = await TestBed.runInInjectionContext(() => requireBrancaAccessEventoGuard(buildRoute('evento-1'), state)); const router = TestBed.inject(Router); expect((result as UrlTree).toString()).toBe(router.parseUrl('/vista-evento/evento-1').toString()); }); it('reindirizza alla vista mensile se il caricamento dell\'evento fallisce', async () => { setup({ roles: ['capo-gruppo'], getEvento: vi.fn().mockReturnValue(throwError(() => new Error('404'))) }); const result = await TestBed.runInInjectionContext(() => requireBrancaAccessEventoGuard(buildRoute('evento-1'), state)); const router = TestBed.inject(Router); expect((result as UrlTree).toString()).toBe(router.parseUrl('/vista-mensile').toString()); }); it('reindirizza alla vista mensile se manca il param id', async () => { setup({ roles: ['capo-gruppo'] }); const result = await TestBed.runInInjectionContext(() => requireBrancaAccessEventoGuard(buildRoute(null), state)); const router = TestBed.inject(Router); expect((result as UrlTree).toString()).toBe(router.parseUrl('/vista-mensile').toString()); }); });