'Polygon', 'coordinates' => [[[13.35, 38.11], [13.37, 38.11], [13.37, 38.13], [13.35, 38.11]]], ]; private const ALTRA_GEOMETRIA = [ 'type' => 'Polygon', 'coordinates' => [[[13.40, 38.11], [13.42, 38.11], [13.42, 38.13], [13.40, 38.11]]], ]; protected function setUp(): void { parent::setUp(); $this->withoutVite(); Storage::fake('public'); Storage::fake('local'); } public function test_la_pagina_e_riservata_all_amministratore(): void { Role::findOr('utente', fn () => Role::create(['name' => 'utente', 'guard_name' => 'web'])); app(PermissionRegistrar::class)->forgetCachedPermissions(); $utente = User::create([ 'name' => 'Utente semplice', 'email' => 'utente@example.test', 'password' => 'password-di-prova', ]); $utente->assignRole('utente'); $this->actingAs($utente)->get(route('piantine.editor'))->assertForbidden(); // Due utenti nella stessa sessione: AuthenticateSession butterebbe fuori il secondo. $this->flushSession(); $this->actingAs($this->admin())->get(route('piantine.editor'))->assertOk(); } public function test_la_pagina_si_apre_su_una_piantina_esistente(): void { $mappa = TerritorioMappa::create(['nome' => 'Zona porto', 'geojson' => json_encode(self::GEOMETRIA)]); $this->actingAs($this->admin()) ->get(route('piantine.editor', $mappa->id)) ->assertOk() ->assertSee('Zona porto'); } public function test_un_disegno_crea_subito_una_bozza_senza_territorio(): void { Livewire::actingAs($this->admin()) ->test(PiantineEditor::class) ->dispatch('geometria-modificata', geometry: self::GEOMETRIA, nuova: true) ->assertDispatched('piantina-aggiornata') ->assertDispatched('editor-indirizzo') ->set('nome', 'Zona porto — lato nord'); $mappa = TerritorioMappa::sole(); $this->assertNull($mappa->territorio_id); $this->assertSame('Zona porto — lato nord', $mappa->nome); $this->assertSame(self::GEOMETRIA, $mappa->geometria()); $this->assertSame(TerritorioMappa::STATO_BOZZA, $mappa->stato()); } public function test_spostare_i_vertici_aggiorna_la_piantina_aperta(): void { $mappa = TerritorioMappa::create(['geojson' => json_encode(self::GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->dispatch('geometria-modificata', geometry: self::ALTRA_GEOMETRIA, nuova: false); $this->assertSame(1, TerritorioMappa::count()); $this->assertSame(self::ALTRA_GEOMETRIA, $mappa->fresh()->geometria()); } public function test_un_disegno_nuovo_con_una_piantina_aperta_non_ne_sostituisce_il_confine(): void { $mappa = TerritorioMappa::create(['geojson' => json_encode(self::GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->dispatch('geometria-modificata', geometry: self::ALTRA_GEOMETRIA, nuova: true); $this->assertSame(2, TerritorioMappa::count()); $this->assertSame(self::GEOMETRIA, $mappa->fresh()->geometria()); } public function test_una_geometria_non_valida_viene_respinta(): void { Livewire::actingAs($this->admin()) ->test(PiantineEditor::class) ->dispatch('geometria-modificata', geometry: ['type' => 'Point', 'coordinates' => [1, 2]], nuova: true) ->dispatch('geometria-modificata', geometry: [ 'type' => 'Polygon', 'coordinates' => [[[0, 0], [1, 0], [0, 0]]], ], nuova: true) ->dispatch('geometria-modificata', geometry: [ 'type' => 'Polygon', 'coordinates' => [[[0, 0], [500, 0], [1, 1], [0, 0]]], ], nuova: true) ->assertDispatched('avviso'); $this->assertSame(0, TerritorioMappa::count()); } public function test_il_territorio_si_crea_dall_editor_con_tutte_le_proprieta(): void { $zona = Zona::create(['nome' => 'Nord', 'attivo' => true]); $tipologia = Tipologia::create(['nome' => 'Residenziale', 'attivo' => true]); $mappa = TerritorioMappa::create(['geojson' => json_encode(self::GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->set('territorioScelto', 'nuovo') ->set('numero', '42') ->set('zonaId', (string) $zona->id) ->set('tipologiaId', (string) $tipologia->id) ->set('confini', "Nord: via Roma\nSud: via Milano") ->call('creaTerritorio') ->assertHasNoErrors() ->assertSet('territorioScelto', fn ($v) => $v !== 'nuovo' && $v !== ''); $territorio = Territorio::where('numero', '42')->sole(); $this->assertTrue((bool) $territorio->attivo); $this->assertSame($zona->id, $territorio->zona_id); $this->assertSame($tipologia->id, $territorio->tipologia_id); $this->assertStringContainsString('via Roma', $territorio->confini); $this->assertSame($territorio->id, $mappa->fresh()->territorio_id); } public function test_in_creazione_i_campi_non_salvano_niente_prima_del_pulsante(): void { $mappa = TerritorioMappa::create(['geojson' => json_encode(self::GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->set('territorioScelto', 'nuovo') ->set('numero', '4'); $this->assertSame(0, Territorio::count()); $this->assertNull($mappa->fresh()->territorio_id); } public function test_un_numero_gia_in_uso_non_crea_un_secondo_territorio(): void { Territorio::create(['numero' => '42', 'attivo' => true]); $mappa = TerritorioMappa::create(['geojson' => json_encode(self::GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->set('territorioScelto', 'nuovo') ->set('numero', '42') ->call('creaTerritorio') ->assertHasErrors('numero'); $this->assertSame(1, Territorio::where('numero', '42')->count()); $this->assertNull($mappa->fresh()->territorio_id); } public function test_scegliere_un_territorio_collega_subito_la_piantina(): void { $territorio = Territorio::create(['numero' => '12', 'attivo' => true, 'confini' => 'Nord: via Verdi']); $mappa = TerritorioMappa::create(['geojson' => json_encode(self::GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->set('territorioScelto', (string) $territorio->id) ->assertHasNoErrors() ->assertSet('numero', '12') ->assertSet('confini', 'Nord: via Verdi'); $this->assertSame($territorio->id, $mappa->fresh()->territorio_id); } /** La tendina leggeva `attivo` senza averlo caricato: tutti "disattivati". */ public function test_la_tendina_segna_disattivato_solo_chi_lo_e(): void { Territorio::create(['numero' => '12', 'attivo' => true]); $mappa = TerritorioMappa::create(['geojson' => json_encode(self::GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->assertSee('Territorio 12') ->assertDontSee('(disattivato)'); } public function test_i_dati_del_territorio_si_salvano_subito_campo_per_campo(): void { $zona = Zona::create(['nome' => 'Sud', 'attivo' => true]); $territorio = Territorio::create(['numero' => '12', 'attivo' => true]); $mappa = TerritorioMappa::create(['territorio_id' => $territorio->id, 'geojson' => json_encode(self::GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->set('confini', 'Est: via Garibaldi') ->set('zonaId', (string) $zona->id) ->assertHasNoErrors(); $territorio->refresh(); $this->assertSame('Est: via Garibaldi', $territorio->confini); $this->assertSame($zona->id, $territorio->zona_id); } public function test_un_campo_non_valido_non_trascina_gli_altri(): void { Territorio::create(['numero' => '7', 'attivo' => true]); $territorio = Territorio::create(['numero' => '12', 'attivo' => true]); $mappa = TerritorioMappa::create(['territorio_id' => $territorio->id, 'geojson' => json_encode(self::GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->set('numero', '7') ->assertHasErrors('numero') ->set('confini', 'Ovest: via Dante'); $territorio->refresh(); $this->assertSame('12', $territorio->numero); $this->assertSame('Ovest: via Dante', $territorio->confini); } public function test_non_si_ruba_il_territorio_a_un_altra_piantina(): void { $territorio = Territorio::create(['numero' => '12', 'attivo' => true]); TerritorioMappa::create(['territorio_id' => $territorio->id, 'geojson' => json_encode(self::GEOMETRIA)]); $seconda = TerritorioMappa::create(['geojson' => json_encode(self::ALTRA_GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $seconda->id]) ->set('territorioScelto', (string) $territorio->id) ->assertHasErrors('territorioScelto') ->assertSet('territorioScelto', ''); $this->assertNull($seconda->fresh()->territorio_id); } public function test_scollegare_lascia_un_etichetta_riconoscibile(): void { $territorio = Territorio::create(['numero' => '12', 'attivo' => true]); $mappa = TerritorioMappa::create(['territorio_id' => $territorio->id, 'geojson' => json_encode(self::GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->set('territorioScelto', ''); $mappa->refresh(); $this->assertNull($mappa->territorio_id); $this->assertSame('Ex territorio 12', $mappa->nome); $this->assertNotNull(Territorio::find($territorio->id)); } public function test_un_territorio_nel_cestino_resta_collegato(): void { $territorio = Territorio::create(['numero' => '12', 'attivo' => true]); $mappa = TerritorioMappa::create(['territorio_id' => $territorio->id, 'geojson' => json_encode(self::GEOMETRIA)]); $territorio->delete(); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->assertSet('territorioScelto', (string) $territorio->id) ->set('nome', 'Prova'); $mappa->refresh(); $this->assertSame($territorio->id, $mappa->territorio_id); $this->assertNotNull($mappa->motivoNonPubblicabile()); } public function test_zona_e_tipologia_si_creano_dall_editor_e_restano_selezionate(): void { $territorio = Territorio::create(['numero' => '12', 'attivo' => true]); $mappa = TerritorioMappa::create(['territorio_id' => $territorio->id, 'geojson' => json_encode(self::GEOMETRIA)]); $componente = Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->set('nuovaZona', 'Litorale') ->call('creaZona') ->assertHasNoErrors() ->set('nuovaTipologia', 'Commerciale') ->call('creaTipologia') ->assertHasNoErrors(); $zona = Zona::where('nome', 'Litorale')->sole(); $tipologia = Tipologia::where('nome', 'Commerciale')->sole(); $componente->assertSet('zonaId', (string) $zona->id); $componente->assertSet('tipologiaId', (string) $tipologia->id); $territorio->refresh(); $this->assertSame($zona->id, $territorio->zona_id); $this->assertSame($tipologia->id, $territorio->tipologia_id); } public function test_una_zona_gia_esistente_non_viene_duplicata(): void { Zona::create(['nome' => 'Nord', 'attivo' => true]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class) ->set('nuovaZona', 'Nord') ->call('creaZona') ->assertHasErrors('nuovaZona'); $this->assertSame(1, Zona::where('nome', 'Nord')->count()); } public function test_pubblica_apre_la_finestra_solo_se_si_puo(): void { $scollegata = TerritorioMappa::create(['geojson' => json_encode(self::GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $scollegata->id]) ->call('pubblica') ->assertNotDispatched('pubblica-piantina') ->assertDispatched('avviso'); $territorio = Territorio::create(['numero' => '12', 'attivo' => true]); $collegata = TerritorioMappa::create(['territorio_id' => $territorio->id, 'geojson' => json_encode(self::ALTRA_GEOMETRIA)]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $collegata->id]) ->call('pubblica') ->assertDispatchedTo(Pubblicazione::class, 'pubblica-piantina', mappaId: $collegata->id); } public function test_scartare_le_modifiche_riporta_il_confine_pubblicato(): void { $territorio = Territorio::create(['numero' => '12', 'attivo' => true]); $mappa = TerritorioMappa::create([ 'territorio_id' => $territorio->id, 'geojson' => json_encode(self::ALTRA_GEOMETRIA), 'geojson_pubblicato' => json_encode(self::GEOMETRIA), 'pubblicata_at' => now(), ]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->call('scartaModifiche'); $this->assertSame(self::GEOMETRIA, $mappa->fresh()->geometria()); } public function test_eliminare_toglie_disegno_e_immagine_ma_non_il_territorio(): void { Storage::disk('public')->put('territori-mappe/piantina-1.jpg', 'x'); $territorio = Territorio::create(['numero' => '12', 'attivo' => true]); $mappa = TerritorioMappa::create([ 'territorio_id' => $territorio->id, 'geojson' => json_encode(self::GEOMETRIA), 'image_path' => 'territori-mappe/piantina-1.jpg', ]); Livewire::actingAs($this->admin()) ->test(PiantineEditor::class, ['mappa' => $mappa->id]) ->call('elimina') ->assertSet('mappaId', null) ->assertDispatched('piantina-rimossa', mappaId: $mappa->id); $this->assertSame(0, TerritorioMappa::count()); $this->assertNotNull(Territorio::find($territorio->id)); Storage::disk('public')->assertMissing('territori-mappe/piantina-1.jpg'); } public function test_dati_mappa_esclude_le_geometrie_illeggibili(): void { TerritorioMappa::create(['geojson' => json_encode(self::GEOMETRIA)]); TerritorioMappa::create(['geojson' => 'non è json']); $dati = Livewire::actingAs($this->admin()) ->test(PiantineEditor::class) ->instance() ->datiMappa(app(\App\Services\Piantine\PiantineArea::class)); $this->assertCount(1, $dati['piantine']); $this->assertSame(TerritorioMappa::STATO_BOZZA, $dati['piantine'][0]['stato']); } private function admin(): User { Role::firstOrCreate(['name' => 'amministratore', 'guard_name' => 'web']); app(PermissionRegistrar::class)->forgetCachedPermissions(); Setting::firstOrCreate([], ['congregazione_nome' => 'Congregazione di prova']); $utente = User::firstOrCreate( ['email' => 'admin@example.test'], ['name' => 'Amministratore', 'password' => 'password-di-prova'], ); $utente->assignRole('amministratore'); return $utente; } }