non viene * compilato, il tag resta letterale nel PHP generato e la pagina muore con un * errore di sintassi. Qui quella classe di errori si vede subito. * * Quello che questi test NON possono coprire: Alpine e il comportamento della * console (apertura automatica, scorrimento, evidenziazione delle zone) girano * nel browser, e qui non c'è un browser. Vanno provati a mano. */ class PaginaBackupImportTest extends TestCase { use RefreshDatabase; protected function setUp(): void { parent::setUp(); // L'immagine di test non contiene public/build: gli asset sono // compilati in uno stage a parte, che serve al runtime e non qui. Senza // questo, ogni pagina morirebbe su "Vite manifest not found" — un // fallimento che non parla del markup, cioe' l'unica cosa che questi // test guardano. Che la build degli asset funzioni lo dice `npm run // build`, non PHPUnit. $this->withoutVite(); } private function admin(): User { Role::findOr('amministratore', fn () => Role::create(['name' => 'amministratore', 'guard_name' => 'web'])); app(PermissionRegistrar::class)->forgetCachedPermissions(); $utente = User::create([ 'name' => 'Amministratore', 'email' => 'admin@example.test', 'password' => 'password-di-prova', ]); $utente->assignRole('amministratore'); return $utente; } public function test_la_pagina_si_apre_per_l_amministratore(): void { $this->actingAs($this->admin()) ->get(route('xml.exchange')) ->assertOk(); } public function test_chi_non_e_amministratore_non_ci_entra(): void { $utente = User::create([ 'name' => 'Assistente', 'email' => 'assistente@example.test', 'password' => 'password-di-prova', ]); $this->actingAs($utente) ->get(route('xml.exchange')) ->assertForbidden(); } /** * Le cinque zone esistono e sono raggiungibili per ancora: l'indice in cima * alla pagina ci salta sopra, e un id sbagliato lo renderebbe un pulsante * che non fa niente. */ public function test_ci_sono_tutte_e_cinque_le_zone_con_la_loro_ancora(): void { $risposta = $this->actingAs($this->admin())->get(route('xml.exchange')); foreach (['zona-backup', 'zona-ripristino', 'zona-pdf', 'zona-xml', 'zona-azzeramento'] as $zona) { $risposta->assertSee('id="' . $zona . '"', false); $risposta->assertSee('tmFocusZona(\'' . $zona . '\'', false); } } /** * La zona pericolosa è l'ultima. È il motivo per cui l'azzeramento è stato * estratto in un componente suo: reso da BackupManager finiva a metà pagina, * fra il ripristino e l'import, che è l'ultimo posto in cui si vuole trovare * un pulsante che cancella tutto. */ public function test_la_zona_pericolosa_e_l_ultima_della_pagina(): void { $html = $this->actingAs($this->admin())->get(route('xml.exchange'))->getContent(); $posizioni = []; foreach (['zona-backup', 'zona-ripristino', 'zona-pdf', 'zona-xml', 'zona-azzeramento'] as $zona) { $posizioni[$zona] = strpos($html, 'id="' . $zona . '"'); $this->assertNotFalse($posizioni[$zona], "Zona {$zona} assente dalla pagina."); } $this->assertSame( ['zona-backup', 'zona-ripristino', 'zona-pdf', 'zona-xml', 'zona-azzeramento'], array_keys($posizioni), 'Ordine atteso delle chiavi.' ); $precedente = -1; foreach ($posizioni as $zona => $posizione) { $this->assertGreaterThan($precedente, $posizione, "La zona {$zona} è fuori ordine."); $precedente = $posizione; } } public function test_la_console_unica_e_nella_pagina(): void { $risposta = $this->actingAs($this->admin())->get(route('xml.exchange')); $risposta->assertSee('tmConsoleOperazioni', false); $risposta->assertSee('class="tm-console"', false); } /** * Ordine di caricamento, che è il motivo per cui quel JavaScript sta in uno *