Files
daily-meal-api/tests/Feature/EngagementReminderNotificationsTest.php
T
leonm bd1b4bba20
CI / 🧪 Tests Laravel (push) Successful in 2m8s
CI / 🐳 Build & Push Image (push) Successful in 31s
refactor: hardcode Bowli mobile scheme
2026-08-11 16:20:27 +02:00

95 lines
3.1 KiB
PHP

<?php
use App\Models\MealPosts;
use App\Models\User;
use App\Notifications\EngagementReminderNotification;
use App\Services\MobileDeepLink;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Http;
uses(RefreshDatabase::class);
it('sends engagement reminders only to eligible mobile users', function () {
app()->setLocale('fr');
Http::fake([
'https://exp.host/*' => Http::response([
'data' => [
['status' => 'ok', 'id' => 'ticket-one'],
],
]),
]);
$eligibleUser = User::factory()->create(['locale' => 'fr']);
$eligibleUser->deviceTokens()->create([
'expo_push_token' => 'ExponentPushToken[eligible]',
'platform' => 'ios',
]);
$recentPoster = User::factory()->create(['locale' => 'fr']);
$recentPoster->deviceTokens()->create([
'expo_push_token' => 'ExponentPushToken[recent-poster]',
'platform' => 'ios',
]);
MealPosts::factory()
->for($recentPoster, 'user')
->create([
'created_at' => now()->subHours(2),
'updated_at' => now()->subHours(2),
]);
User::factory()->create(['locale' => 'fr']);
$suspendedUser = User::factory()->create([
'locale' => 'fr',
'suspended_at' => now(),
]);
$suspendedUser->deviceTokens()->create([
'expo_push_token' => 'ExponentPushToken[suspended]',
'platform' => 'ios',
]);
$this->artisan('notifications:send-engagement-reminders')
->expectsOutput('1 engagement reminder notification(s) sent.')
->assertSuccessful();
Http::assertSentCount(1);
Http::assertSent(function (Request $request): bool {
$payload = $request->data()[0];
return $payload['to'] === 'ExponentPushToken[eligible]'
&& $payload['data']['type'] === 'engagement_reminder'
&& in_array($payload['data']['url'], [
'bowli://create',
'bowli://profile/workouts?create=1',
], true);
});
});
it('uses the hard-coded localized reminder copy', function () {
foreach (['fr', 'en'] as $locale) {
app()->setLocale($locale);
foreach (EngagementReminderNotification::messageKeys() as $messageKey) {
$expectedPath = $messageKey === 'workout_checkin'
? 'profile/workouts?create=1'
: 'create';
$payload = (new EngagementReminderNotification($messageKey))
->toExpoPush(User::factory()->make(['locale' => $locale]));
expect($payload['title'])->toBeString()->not->toBeEmpty()
->and($payload['body'])->toBeString()->not->toBeEmpty()
->and($payload['data']['message_key'])->toBe($messageKey)
->and($payload['data']['url'])->toBe("bowli://{$expectedPath}");
}
}
});
it('builds mobile deep links with the Bowli scheme', function () {
expect(MobileDeepLink::to('/create'))->toBe('bowli://create')
->and(MobileDeepLink::to('strava/callback', ['code' => 'abc 123']))->toBe('bowli://strava/callback?code=abc%20123');
});