145 lines
4.6 KiB
PHP
145 lines
4.6 KiB
PHP
<?php
|
|
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Str;
|
|
use Laravel\Sanctum\Sanctum;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
function storeMobileNotification(User $user, array $data, ?string $readAt = null): string
|
|
{
|
|
$id = (string) Str::uuid();
|
|
|
|
DB::table('notifications')->insert([
|
|
'id' => $id,
|
|
'type' => $data['type'],
|
|
'notifiable_type' => User::class,
|
|
'notifiable_id' => $user->getKey(),
|
|
'data' => json_encode($data, JSON_THROW_ON_ERROR),
|
|
'read_at' => $readAt,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
return $id;
|
|
}
|
|
|
|
it('lists paginated mobile notifications with the unread count', function () {
|
|
$user = User::factory()->create();
|
|
$readNotificationId = storeMobileNotification($user, [
|
|
'type' => 'new_follower',
|
|
'category' => 'social',
|
|
'title' => 'Nouvel abonné',
|
|
'body' => 'Alex vous suit maintenant.',
|
|
'url' => 'bowli://users/123',
|
|
], now()->toISOString());
|
|
$unreadNotificationId = storeMobileNotification($user, [
|
|
'type' => 'payment_failed',
|
|
'category' => 'account',
|
|
'title' => 'Paiement échoué',
|
|
'body' => 'Vérifiez votre moyen de paiement.',
|
|
'url' => 'bowli://profile/settings/billing',
|
|
]);
|
|
|
|
DB::table('notifications')->insert([
|
|
'id' => (string) Str::uuid(),
|
|
'type' => 'filament',
|
|
'notifiable_type' => User::class,
|
|
'notifiable_id' => $user->getKey(),
|
|
'data' => json_encode(['format' => 'filament'], JSON_THROW_ON_ERROR),
|
|
'read_at' => null,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
Sanctum::actingAs($user);
|
|
|
|
$this->getJson('/api/notifications?per_page=1')
|
|
->assertOk()
|
|
->assertJsonCount(1, 'data')
|
|
->assertJsonPath('data.0.id', $unreadNotificationId)
|
|
->assertJsonPath('data.0.readAt', null)
|
|
->assertJsonPath('meta.total', 2)
|
|
->assertJsonPath('unreadCount', 1);
|
|
|
|
$this->getJson('/api/notifications?per_page=1&page=2')
|
|
->assertOk()
|
|
->assertJsonPath('data.0.id', $readNotificationId);
|
|
});
|
|
|
|
it('marks only the authenticated users notifications as read', function () {
|
|
$user = User::factory()->create();
|
|
$otherUser = User::factory()->create();
|
|
$firstId = storeMobileNotification($user, [
|
|
'type' => 'new_follower',
|
|
'category' => 'social',
|
|
'title' => 'Nouvel abonné',
|
|
'body' => 'Alex vous suit maintenant.',
|
|
'url' => 'bowli://users/123',
|
|
]);
|
|
storeMobileNotification($user, [
|
|
'type' => 'meal_commented',
|
|
'category' => 'social',
|
|
'title' => 'Nouveau commentaire',
|
|
'body' => 'Un commentaire.',
|
|
'url' => 'bowli://meals/123',
|
|
]);
|
|
$otherId = storeMobileNotification($otherUser, [
|
|
'type' => 'payment_failed',
|
|
'category' => 'account',
|
|
'title' => 'Paiement échoué',
|
|
'body' => 'Paiement échoué.',
|
|
'url' => 'bowli://profile/settings/billing',
|
|
]);
|
|
|
|
Sanctum::actingAs($user);
|
|
|
|
$this->patchJson("/api/notifications/{$otherId}/read")->assertNotFound();
|
|
|
|
$this->patchJson("/api/notifications/{$firstId}/read")
|
|
->assertOk()
|
|
->assertJsonPath('data.id', $firstId)
|
|
->assertJsonPath('data.readAt', fn ($value): bool => is_string($value));
|
|
|
|
$this->getJson('/api/notifications/unread-count')
|
|
->assertOk()
|
|
->assertJsonPath('data.count', 1);
|
|
|
|
$this->patchJson('/api/notifications/read-all')
|
|
->assertOk()
|
|
->assertJsonPath('data.updated', 1);
|
|
|
|
$this->getJson('/api/notifications/unread-count')
|
|
->assertOk()
|
|
->assertJsonPath('data.count', 0);
|
|
});
|
|
|
|
it('shows and updates notification preferences', function () {
|
|
$user = User::factory()->create();
|
|
|
|
Sanctum::actingAs($user);
|
|
|
|
$this->getJson('/api/notification-preferences')
|
|
->assertOk()
|
|
->assertJsonPath('data.socialNotificationsEnabled', true)
|
|
->assertJsonPath('data.engagementRemindersEnabled', true);
|
|
|
|
$this->patchJson('/api/notification-preferences', [
|
|
'socialNotificationsEnabled' => false,
|
|
'engagementRemindersEnabled' => false,
|
|
])
|
|
->assertOk()
|
|
->assertJsonPath('data.socialNotificationsEnabled', false)
|
|
->assertJsonPath('data.engagementRemindersEnabled', false);
|
|
|
|
expect($user->fresh())
|
|
->social_notifications_enabled->toBeFalse()
|
|
->engagement_reminders_enabled->toBeFalse();
|
|
|
|
$this->patchJson('/api/notification-preferences', [
|
|
'socialNotificationsEnabled' => 'no',
|
|
])->assertUnprocessable();
|
|
});
|