Files
termanager2/tests/Feature/InvioLinkTest.php
Francesco Picone eda3c3f989 ++ elenco dei territori assegnati: pulsante Rientro su ogni riga
Porta alla registrazione del rientro e torna all'elenco (data-ritorno);
solo con il permesso territori.return.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 15:32:07 +02:00

274 lines
11 KiB
PHP

<?php
namespace Tests\Feature;
use App\Livewire\Assegnazioni\Assegna;
use App\Livewire\Assegnazioni\ElencoAssegnati;
use App\Livewire\Proclamatori\ProclamatoreCreate;
use App\Livewire\Settings\XmlExchange;
use App\Models\AnnoTeocratico;
use App\Models\Assegnazione;
use App\Models\Proclamatore;
use App\Models\Setting;
use App\Models\Territorio;
use App\Models\User;
use Database\Seeders\RolesAndPermissionsSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Storage;
use Livewire\Livewire;
use Spatie\Activitylog\Models\Activity;
use Tests\TestCase;
/**
* L'invio del link della piantina dopo l'assegnazione: copia link o
* "Condividi" (menu del telefono), con il destinatario scelto da chi usa
* l'app. I proclamatori non hanno più email né telefono (19 ottobre 2026).
*/
class InvioLinkTest extends TestCase
{
use RefreshDatabase;
private User $admin;
protected function setUp(): void
{
parent::setUp();
$this->withoutVite();
Storage::fake('public');
$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');
}
private function assegna(Proclamatore $proclamatore, Territorio $territorio)
{
return Livewire::actingAs($this->admin)->test(Assegna::class)
->set('territorio_id', $territorio->id)
->set('proclamatore_id', $proclamatore->id)
->set('assigned_at', now()->format('Y-m-d'))
->call('save');
}
private function territorioConPdf(string $numero = '7'): Territorio
{
Storage::disk('public')->put("territori-pdf/t{$numero}.pdf", '%PDF-1.4');
return Territorio::create(['numero' => $numero, 'attivo' => true, 'pdf_path' => "territori-pdf/t{$numero}.pdf"]);
}
private function mario(): Proclamatore
{
return Proclamatore::create(['nome' => 'Mario', 'cognome' => 'Rossi', 'attivo' => true]);
}
// ─── Niente contatti nei proclamatori ───────────────────────
public function test_i_proclamatori_non_hanno_ne_email_ne_telefono(): void
{
$this->assertFalse(Schema::hasColumn('proclamatori', 'email'));
$this->assertFalse(Schema::hasColumn('proclamatori', 'telefono'));
$this->actingAs($this->admin)->get(route('proclamatori.create'))
->assertOk()
->assertDontSee('id="telefono"', false)
->assertDontSee('id="email"', false);
Livewire::actingAs($this->admin)->test(ProclamatoreCreate::class)
->set('nome', 'Anna')->set('cognome', 'Verdi')
->call('save')
->assertHasNoErrors();
$this->assertSame(['Verdi Anna'], Proclamatore::all()->map->nome_completo->all());
}
public function test_un_xml_vecchio_con_email_e_telefono_si_importa_ignorandoli(): void
{
$this->actingAs($this->admin);
$this->mario();
$xml = (new XmlExchange())->currentXmlBackup();
$vecchio = str_replace('<cognome>', '<email>m@example.test</email><telefono>3331234567</telefono><cognome>', $xml);
$this->assertArrayNotHasKey('error', (new XmlExchange())->importXmlFromContent($vecchio));
$this->assertSame('Rossi Mario', Proclamatore::sole()->nome_completo);
$this->assertStringNotContainsString('<telefono>', (new XmlExchange())->currentXmlBackup());
}
// ─── Dopo l'assegnazione ────────────────────────────────────
public function test_dopo_l_assegnazione_si_sceglie_tra_copia_link_e_condividi(): void
{
$pagina = $this->assegna($this->mario(), $this->territorioConPdf())
->assertHasNoErrors()
->assertNoRedirect();
$assegnazione = Assegnazione::sole();
$this->assertTrue($assegnazione->link_da_inviare);
$this->assertFalse($assegnazione->link_sent);
$link = $assegnazione->shortPdfUrl();
$pagina->assertSet('invioId', $assegnazione->id)
->assertSee('Territorio N° 7 assegnato a Rossi Mario')
->assertSee('Come vuoi mandare il link della piantina?')
->assertSee($link)
->assertSee('Copia link')
->assertSee('Condividi…')
// Il messaggio per "Condividi", con il link.
->assertSeeHtml('data-messaggio="Ciao Mario, ti è stato assegnato il territorio N° 7. Ecco la piantina: ' . e($link) . '"')
->assertDontSee('wa.me', false)
->assertDontSee('WhatsApp')
->assertSee('Hai inviato il link?');
}
public function test_si_dice_inviato_solo_dopo_aver_scelto_un_canale(): void
{
$mario = $this->mario();
$this->assegna($mario, $this->territorioConPdf())
->call('concludiInvio', true)
->assertNoRedirect()
->assertSet('erroreInvio', 'Scegli prima come mandare il link.')
->call('canale', 'condividi')
->call('concludiInvio', true)
->assertRedirect(route('assegnazioni.assegna'));
$assegnazione = Assegnazione::sole();
$this->assertTrue($assegnazione->link_sent);
$this->assertFalse($assegnazione->link_da_inviare);
$this->assertSame('condividi', $assegnazione->link_canale);
$log = Activity::where('description', 'link_inviato')->sole();
$this->assertSame('condividi', $log->properties['canale']);
$this->assertSame($mario->id, $log->properties['proclamatore_id']);
$this->assertStringNotContainsString('Rossi', json_encode($log->properties));
}
public function test_whatsapp_ed_email_non_sono_piu_canali(): void
{
$this->assegna($this->mario(), $this->territorioConPdf())
->call('canale', 'whatsapp')
->assertSet('canaleUsato', null)
->call('canale', 'email')
->assertSet('canaleUsato', null)
->call('canale', 'copia')
->assertSet('canaleUsato', 'copia');
$this->assertSame(['copia', 'condividi'], Assegnazione::CANALI_ATTIVI);
}
public function test_se_non_si_conclude_l_invio_l_assegnazione_lo_segnala(): void
{
$this->assegna($this->mario(), $this->territorioConPdf());
$assegnazione = Assegnazione::sole();
// La pagina viene chiusa senza rispondere: l'invio è perso, l'avviso resta
// nell'elenco, e "Invia link" chiede alla pagina di riaprirlo.
Livewire::withoutLazyLoading()->actingAs($this->admin)->test(ElencoAssegnati::class)
->assertSee('Link ancora da inviare')
->assertSeeHtml("\$dispatch('apri-invio', { assegnazioneId: {$assegnazione->id} })");
Livewire::actingAs($this->admin)->test(Assegna::class)
->assertSet('invioId', null)
->dispatch('apri-invio', assegnazioneId: $assegnazione->id)
->assertSee('Hai inviato il link?')
->call('concludiInvio', false)
->assertRedirect(route('assegnazioni.assegna'));
// "No, non ancora": la procedura è finita, ma il link resta da inviare.
$this->assertTrue($assegnazione->fresh()->link_in_sospeso);
$this->get(route('territori.show', $assegnazione->territorio_id))
->assertSee('Il link della piantina è ancora da inviare');
// Segnato come inviato dall'elenco: l'avviso sparisce.
Livewire::withoutLazyLoading()->actingAs($this->admin)->test(ElencoAssegnati::class)
->call('toggleLinkSent', $assegnazione->id)
->assertDontSee('Link ancora da inviare');
$this->assertFalse($assegnazione->fresh()->link_in_sospeso);
}
public function test_condividere_dall_elenco_segna_il_link_come_inviato(): void
{
$this->assegna($this->mario(), $this->territorioConPdf());
$assegnazione = Assegnazione::sole();
Livewire::withoutLazyLoading()->actingAs($this->admin)->test(ElencoAssegnati::class)
->assertSeeHtml('data-id="' . $assegnazione->id . '"')
->assertDontSee('wa.me', false)
->call('segnaCondiviso', $assegnazione->id)
->assertDontSee('Link ancora da inviare');
$this->assertTrue($assegnazione->fresh()->link_sent);
$this->assertSame('condividi', $assegnazione->fresh()->link_canale);
}
public function test_dalla_scheda_territorio_si_riprende_l_invio(): void
{
$this->assegna($this->mario(), $this->territorioConPdf());
$assegnazione = Assegnazione::sole();
$this->actingAs($this->admin)
->get(route('assegnazioni.assegna', ['invia' => $assegnazione->id]))
->assertOk()
->assertSee('Hai inviato il link?');
}
public function test_senza_pdf_non_c_e_un_link_da_inviare(): void
{
$territorio = Territorio::create(['numero' => '9', 'attivo' => true]);
$this->assegna($this->mario(), $territorio)
->assertSee('non ha un PDF')
->call('concludiInvio', false);
$this->assertFalse(Assegnazione::sole()->link_in_sospeso);
}
public function test_le_assegnazioni_gia_esistenti_non_vengono_segnalate(): void
{
$vecchia = Assegnazione::create([
'territorio_id' => $this->territorioConPdf()->id,
'proclamatore_id' => $this->mario()->id,
'anno_teocratico_id' => AnnoTeocratico::sole()->id,
'assigned_at' => now(),
'created_by' => $this->admin->id,
]);
$this->assertFalse($vecchia->fresh()->link_in_sospeso);
}
public function test_l_xml_porta_con_se_lo_stato_dell_invio(): void
{
$this->actingAs($this->admin);
$this->assegna($this->mario(), $this->territorioConPdf())->call('canale', 'copia')->call('concludiInvio', true);
$xml = (new XmlExchange())->currentXmlBackup();
$this->assertArrayNotHasKey('error', (new XmlExchange())->importXmlFromContent($xml));
$assegnazione = Assegnazione::sole();
$this->assertTrue($assegnazione->link_sent);
$this->assertFalse($assegnazione->link_da_inviare);
$this->assertSame('copia', $assegnazione->link_canale);
}
// ─── Nuovo territorio dal designer ──────────────────────────
public function test_nuovo_territorio_porta_al_designer_delle_piantine(): void
{
$this->actingAs($this->admin)
->get(route('territori.index'))
->assertSee(route('piantine.editor', ['nuovo' => 1]), false);
}
public function test_dall_elenco_degli_assegnati_si_va_al_rientro(): void
{
$this->assegna($this->mario(), $this->territorioConPdf('7'));
$a = Assegnazione::sole();
Livewire::withoutLazyLoading()->actingAs($this->admin)->test(ElencoAssegnati::class)
->assertSee('Rientro')
->assertSee(route('assegnazioni.rientra', $a), false);
}
}