withoutVite(); $this->seed(RolesAndPermissionsSeeder::class); Setting::firstOrCreate([], ['congregazione_nome' => 'Congregazione di prova']); AnnoTeocratico::create(['label' => '2026-2027', 'start_date' => '2026-09-01', 'end_date' => '2027-08-31']); $this->admin = User::create(['name' => 'Admin', 'email' => 'admin@example.test', 'password' => 'password-di-prova']); $this->admin->assignRole('amministratore'); } // ─── Validazione ──────────────────────────────────────────── public function test_un_percorso_interno_diventa_l_url_di_ritorno(): void { $this->assertSame(url('/territori?filterZona=3&page=2'), Ritorno::valida('/territori?filterZona=3&page=2')); $this->assertSame(url('/'), Ritorno::valida('/')); } #[DataProvider('ritorniNonValidi')] public function test_un_ritorno_esterno_o_malformato_si_ignora(mixed $valore): void { $this->assertNull(Ritorno::valida($valore)); } public static function ritorniNonValidi(): array { return [ 'vuoto' => [''], 'null' => [null], 'array' => [['/territori']], 'url completo' => ['https://altro.sito/x'], 'senza schema' => ['//altro.sito/x'], 'barra rovesciata' => ['/\\altro.sito'], 'relativo' => ['territori'], 'javascript' => ['javascript:alert(1)'], 'a capo' => ["/territori\r\nX: y"], 'livewire' => ['/livewire/update'], ]; } // ─── Dopo la conferma ─────────────────────────────────────── private function assegnazioneAperta(): Assegnazione { $territorio = Territorio::create(['numero' => '35', 'attivo' => true]); $proclamatore = Proclamatore::create(['nome' => 'Mario', 'cognome' => 'Rossi', 'attivo' => true]); return Assegnazione::create([ 'territorio_id' => $territorio->id, 'proclamatore_id' => $proclamatore->id, 'anno_teocratico_id' => AnnoTeocratico::sole()->id, 'assigned_at' => now()->subDays(10), 'created_by' => $this->admin->id, ]); } public function test_il_rientro_torna_all_elenco_filtrato_da_cui_si_era_partiti(): void { $assegnazione = $this->assegnazioneAperta(); Livewire::withQueryParams(['da' => '/territori?filterStato=da_rientrare&page=2']) ->actingAs($this->admin) ->test(Rientra::class, ['assegnazione' => $assegnazione]) ->call('save') ->assertRedirect(url('/territori?filterStato=da_rientrare&page=2')); } public function test_senza_pagina_di_partenza_il_rientro_va_alla_scheda_come_prima(): void { $assegnazione = $this->assegnazioneAperta(); Livewire::actingAs($this->admin) ->test(Rientra::class, ['assegnazione' => $assegnazione]) ->call('save') ->assertRedirect(route('territori.show', $assegnazione->territorio_id)); } public function test_un_ritorno_verso_l_esterno_non_viene_seguito(): void { $assegnazione = $this->assegnazioneAperta(); Livewire::withQueryParams(['da' => '//altro.sito/phishing']) ->actingAs($this->admin) ->test(Rientra::class, ['assegnazione' => $assegnazione]) ->assertSet('ritorno', null) ->call('save') ->assertRedirect(route('territori.show', $assegnazione->territorio_id)); } public function test_la_modifica_del_proclamatore_torna_alla_ricerca(): void { $mario = Proclamatore::create(['nome' => 'Mario', 'cognome' => 'Rossi', 'attivo' => true]); Livewire::withQueryParams(['da' => '/proclamatori?search=Rossi']) ->actingAs($this->admin) ->test(ProclamatoreEdit::class, ['proclamatore' => $mario]) ->set('nome', 'Mario Luigi') ->call('save') ->assertRedirect(url('/proclamatori?search=Rossi')); } // ─── Annulla e "Torna indietro" ───────────────────────────── public function test_annulla_e_torna_indietro_portano_alla_pagina_di_partenza(): void { $assegnazione = $this->assegnazioneAperta(); $partenza = '/territori?search=35'; $this->actingAs($this->admin) ->get(route('assegnazioni.rientra', $assegnazione) . '?da=' . urlencode($partenza)) ->assertOk() ->assertSee('Torna indietro') ->assertSee('href="' . e(url($partenza)) . '"', false); } public function test_senza_partenza_le_etichette_restano_quelle_di_prima(): void { $assegnazione = $this->assegnazioneAperta(); $this->actingAs($this->admin) ->get(route('assegnazioni.rientra', $assegnazione)) ->assertOk() ->assertSee('Torna al territorio') ->assertDontSee('Torna indietro'); } // ─── Gli elenchi ricordano filtri e ordinamento ───────────── public function test_l_elenco_territori_legge_filtri_e_ordinamento_dall_indirizzo(): void { Livewire::withQueryParams(['search' => '35', 'filterStato' => 'assegnato', 'sortField' => 'zona', 'sortDirection' => 'desc']) ->actingAs($this->admin) ->test(TerritorioIndex::class) ->assertSet('search', '35') ->assertSet('filterStato', 'assegnato') ->assertSet('sortField', 'zona') ->assertSet('sortDirection', 'desc'); } public function test_l_elenco_proclamatori_legge_la_ricerca_dall_indirizzo(): void { Livewire::withQueryParams(['search' => 'Rossi', 'filtroStato' => 'attivi']) ->actingAs($this->admin) ->test(ProclamatoreIndex::class) ->assertSet('search', 'Rossi') ->assertSet('filtroStato', 'attivi'); } public function test_i_link_verso_schede_e_operazioni_portano_il_ritorno(): void { Territorio::create(['numero' => '35', 'attivo' => true]); $html = $this->actingAs($this->admin)->get(route('territori.index'))->assertOk()->getContent(); // Il link alla scheda è marcato: il JS gli aggiunge ?da= al momento del clic. $this->assertMatchesRegularExpression('/]*\bdata-ritorno\b)(?=[^>]*href="[^"]*\/territori\/\d+")[^>]*>/s', $html); } }