Publication initiale de RelaisSMS : documentation et sources nettoyees

This commit is contained in:
2026-10-21 09:29:39 +02:00
commit ac186b03b1
158 changed files with 24818 additions and 0 deletions
+440
View File
@@ -0,0 +1,440 @@
<?php
namespace Tests\Feature;
use App\Models\Contact;
use App\Models\ContactGroup;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ContactManagementTest extends TestCase
{
use RefreshDatabase;
public function test_authenticated_user_can_create_group_and_local_contact(): void
{
$user = User::factory()->create();
$this->actingAs($user)
->post('/contact-groups', [
'name' => 'Benevoles',
'description' => 'Equipe locale',
'is_favorite' => '1',
])
->assertRedirect('/contacts');
$group = ContactGroup::query()->where('name', 'Benevoles')->firstOrFail();
$response = $this->actingAs($user)
->post('/contacts', [
'first_name' => 'Marie',
'last_name' => 'Durand',
'organization' => 'AFPMA',
'email' => 'marie@example.test',
'raw_phone_number' => '06 11 11 00 03',
'phone_label' => 'Mobile',
'group_ids' => [$group->id],
'sms_opt_out' => '1',
'is_favorite' => '1',
]);
$contact = Contact::query()->where('email', 'marie@example.test')->firstOrFail();
$response->assertRedirect(route('contacts.show', $contact));
$this->assertDatabaseHas('contacts', [
'id' => $contact->id,
'source' => 'local',
'sms_opt_out' => true,
'is_favorite' => true,
]);
$this->assertDatabaseHas('contact_contact_group', [
'contact_id' => $contact->id,
'contact_group_id' => $group->id,
]);
$this->assertDatabaseHas('contact_phone_numbers', [
'contact_id' => $contact->id,
'raw_number' => '06 11 11 00 03',
'normalized_number' => '+33611110003',
'country' => 'FR',
'is_valid' => true,
'is_mobile' => true,
]);
}
public function test_contacts_can_be_searched_by_name_and_phone_number(): void
{
$user = User::factory()->create();
$contact = Contact::query()->create([
'source' => 'local',
'first_name' => 'Jean',
'last_name' => 'Martin',
'email' => 'jean@example.test',
]);
$contact->phoneNumbers()->create([
'raw_number' => '06 11 11 00 01',
'normalized_number' => '+33611110001',
'country' => 'FR',
'is_valid' => true,
'is_mobile' => true,
'is_primary' => true,
]);
$this->actingAs($user)
->get('/contacts?q=Martin')
->assertOk()
->assertSee('Jean Martin')
->assertSee('+33611110001');
$this->actingAs($user)
->get('/contacts?q=11110001')
->assertOk()
->assertSee('Jean Martin');
}
public function test_contacts_default_mobile_filter_includes_stale_normalized_mobile_numbers(): void
{
$user = User::factory()->create();
$contact = Contact::query()->create([
'source' => 'carddav',
'external_id' => 'uid-yveline',
'first_name' => 'Yveline',
'last_name' => 'Mobile',
]);
$contact->phoneNumbers()->create([
'raw_number' => '064-201-4207',
'normalized_number' => '+33642014207',
'country' => 'FR',
'is_valid' => true,
'is_mobile' => false,
'is_primary' => true,
]);
$this->actingAs($user)
->get('/contacts')
->assertOk()
->assertSee('Yveline Mobile')
->assertSee('Mobile detecte');
}
public function test_authenticated_user_can_update_contact(): void
{
$user = User::factory()->create();
$oldGroup = ContactGroup::query()->create([
'source' => 'local',
'name' => 'Anciens',
'slug' => 'anciens',
]);
$newGroup = ContactGroup::query()->create([
'source' => 'local',
'name' => 'Membres',
'slug' => 'membres',
]);
$contact = Contact::query()->create([
'source' => 'local',
'first_name' => 'Jean',
'last_name' => 'Martin',
'email' => 'jean@example.test',
]);
$contact->groups()->attach($oldGroup);
$contact->phoneNumbers()->create([
'label' => 'Mobile',
'raw_number' => '06 11 11 00 01',
'normalized_number' => '+33611110001',
'country' => 'FR',
'is_valid' => true,
'is_mobile' => true,
'is_primary' => true,
]);
$this->actingAs($user)
->put(route('contacts.update', $contact), [
'first_name' => 'Jeanne',
'last_name' => 'Martin',
'email' => 'jeanne@example.test',
'raw_phone_number' => '07 55 55 00 04',
'phone_label' => 'Portable',
'group_ids' => [$newGroup->id],
'is_favorite' => '1',
])
->assertRedirect(route('contacts.show', $contact));
$this->assertDatabaseHas('contacts', [
'id' => $contact->id,
'first_name' => 'Jeanne',
'email' => 'jeanne@example.test',
'sms_opt_out' => false,
'is_favorite' => true,
]);
$this->assertDatabaseMissing('contact_contact_group', [
'contact_id' => $contact->id,
'contact_group_id' => $oldGroup->id,
]);
$this->assertDatabaseHas('contact_contact_group', [
'contact_id' => $contact->id,
'contact_group_id' => $newGroup->id,
]);
$this->assertDatabaseHas('contact_phone_numbers', [
'contact_id' => $contact->id,
'label' => 'Portable',
'raw_number' => '07 55 55 00 04',
'normalized_number' => '+33755550004',
'is_mobile' => true,
]);
}
public function test_imported_contacts_cannot_be_edited_or_deleted(): void
{
$user = User::factory()->create();
$contact = Contact::query()->create([
'source' => 'carddav',
'external_id' => 'remote-1',
'first_name' => 'Jean',
'last_name' => 'Importe',
]);
$this->actingAs($user)
->get(route('contacts.edit', $contact))
->assertForbidden();
$this->actingAs($user)
->put(route('contacts.update', $contact), [
'last_name' => 'Modifie',
])
->assertForbidden();
$this->actingAs($user)
->delete(route('contacts.destroy', $contact))
->assertForbidden();
$this->assertDatabaseHas('contacts', [
'id' => $contact->id,
'last_name' => 'Importe',
'deleted_at' => null,
]);
}
public function test_authenticated_user_can_toggle_favorite_on_imported_contact(): void
{
$user = User::factory()->create();
$contact = Contact::query()->create([
'source' => 'carddav',
'external_id' => 'remote-favorite',
'first_name' => 'Yveline',
'last_name' => 'Importee',
'is_favorite' => false,
]);
$this->actingAs($user)
->patch(route('contacts.favorite', $contact), [
'is_favorite' => '1',
])
->assertRedirect();
$this->assertDatabaseHas('contacts', [
'id' => $contact->id,
'source' => 'carddav',
'is_favorite' => true,
]);
$this->actingAs($user)
->patch(route('contacts.favorite', $contact), [
'is_favorite' => '0',
])
->assertRedirect();
$this->assertDatabaseHas('contacts', [
'id' => $contact->id,
'source' => 'carddav',
'is_favorite' => false,
]);
}
public function test_authenticated_user_can_toggle_sms_opt_out_on_imported_contact(): void
{
$user = User::factory()->create();
$contact = Contact::query()->create([
'source' => 'galette',
'external_id' => 'remote-opt-out',
'first_name' => 'Claire',
'last_name' => 'Importee',
'sms_opt_out' => false,
]);
$this->actingAs($user)
->patch(route('contacts.opt-out', $contact), [
'sms_opt_out' => '1',
])
->assertRedirect();
$this->assertDatabaseHas('contacts', [
'id' => $contact->id,
'source' => 'galette',
'sms_opt_out' => true,
]);
$this->actingAs($user)
->patch(route('contacts.opt-out', $contact), [
'sms_opt_out' => '0',
])
->assertRedirect();
$this->assertDatabaseHas('contacts', [
'id' => $contact->id,
'source' => 'galette',
'sms_opt_out' => false,
]);
}
public function test_authenticated_user_can_delete_contact(): void
{
$user = User::factory()->create();
$contact = Contact::query()->create([
'source' => 'local',
'first_name' => 'Jean',
'last_name' => 'Martin',
]);
$this->actingAs($user)
->delete(route('contacts.destroy', $contact))
->assertRedirect(route('contacts.index'));
$this->assertSoftDeleted('contacts', [
'id' => $contact->id,
]);
}
public function test_authenticated_user_can_update_and_delete_group(): void
{
$user = User::factory()->create();
$group = ContactGroup::query()->create([
'source' => 'local',
'name' => 'Benevoles',
'slug' => 'benevoles',
]);
$contact = Contact::query()->create([
'source' => 'local',
'first_name' => 'Marie',
'last_name' => 'Durand',
]);
$contact->groups()->attach($group);
$this->actingAs($user)
->put(route('contact-groups.update', $group), [
'name' => 'Equipe accueil',
'description' => 'Permanences',
'is_favorite' => '1',
])
->assertRedirect(route('contacts.index', ['group' => $group->id]));
$this->assertDatabaseHas('contact_groups', [
'id' => $group->id,
'name' => 'Equipe accueil',
'slug' => 'equipe-accueil',
'description' => 'Permanences',
'is_favorite' => true,
]);
$this->actingAs($user)
->delete(route('contact-groups.destroy', $group))
->assertRedirect(route('contacts.index'));
$this->assertSoftDeleted('contact_groups', [
'id' => $group->id,
]);
$this->assertDatabaseMissing('contact_contact_group', [
'contact_id' => $contact->id,
'contact_group_id' => $group->id,
]);
}
public function test_authenticated_user_can_update_local_group_members(): void
{
$user = User::factory()->create();
$group = ContactGroup::query()->create([
'source' => 'local',
'name' => 'Benevoles',
'slug' => 'benevoles',
]);
$kept = Contact::query()->create([
'source' => 'local',
'first_name' => 'Marie',
'last_name' => 'Durand',
]);
$removed = Contact::query()->create([
'source' => 'local',
'first_name' => 'Paul',
'last_name' => 'Ancien',
]);
$addedImported = Contact::query()->create([
'source' => 'carddav',
'external_id' => 'remote-added',
'first_name' => 'Claire',
'last_name' => 'Importee',
]);
$group->contacts()->attach([$kept->id, $removed->id]);
$this->actingAs($user)
->put(route('contact-groups.update', $group), [
'name' => 'Benevoles',
'members_submitted' => '1',
'contact_ids' => [$kept->id, $addedImported->id],
])
->assertRedirect(route('contacts.index', ['group' => $group->id]));
$this->assertDatabaseHas('contact_contact_group', [
'contact_id' => $kept->id,
'contact_group_id' => $group->id,
]);
$this->assertDatabaseHas('contact_contact_group', [
'contact_id' => $addedImported->id,
'contact_group_id' => $group->id,
]);
$this->assertDatabaseMissing('contact_contact_group', [
'contact_id' => $removed->id,
'contact_group_id' => $group->id,
]);
}
public function test_imported_groups_cannot_be_edited_or_deleted(): void
{
$user = User::factory()->create();
$group = ContactGroup::query()->create([
'source' => 'galette',
'external_id' => 'remote-group',
'name' => 'Groupe importe',
'slug' => 'galette-groupe-importe',
]);
$this->actingAs($user)
->get(route('contact-groups.edit', $group))
->assertForbidden();
$this->actingAs($user)
->put(route('contact-groups.update', $group), [
'name' => 'Modifie',
])
->assertForbidden();
$this->actingAs($user)
->delete(route('contact-groups.destroy', $group))
->assertForbidden();
$this->assertDatabaseHas('contact_groups', [
'id' => $group->id,
'name' => 'Groupe importe',
'deleted_at' => null,
]);
}
public function test_guest_cannot_access_contacts(): void
{
$this->get('/contacts')
->assertRedirect('/login');
}
}