158 lines
4.8 KiB
PHP
158 lines
4.8 KiB
PHP
<?php
|
|
|
|
use App\Broadcasting\ExpoPushChannel;
|
|
use App\Models\DeviceToken;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Http\Client\Request;
|
|
use Illuminate\Notifications\Notification;
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
it('sends expo push notifications to every registered device token', function () {
|
|
Http::fake([
|
|
'https://exp.host/*' => Http::response([
|
|
'data' => [
|
|
['status' => 'ok', 'id' => 'ticket-one'],
|
|
['status' => 'ok', 'id' => 'ticket-two'],
|
|
],
|
|
]),
|
|
]);
|
|
|
|
$user = User::factory()->create();
|
|
$user->deviceTokens()->create([
|
|
'expo_push_token' => 'ExponentPushToken[first]',
|
|
'platform' => 'ios',
|
|
]);
|
|
$user->deviceTokens()->create([
|
|
'expo_push_token' => 'ExponentPushToken[second]',
|
|
'platform' => 'android',
|
|
]);
|
|
|
|
(new ExpoPushChannel)->send($user, expoPushTestNotification());
|
|
|
|
Http::assertSent(fn (Request $request) => $request->url() === 'https://exp.host/--/api/v2/push/send'
|
|
&& $request->data() === [
|
|
[
|
|
'to' => 'ExponentPushToken[first]',
|
|
'title' => 'Nouveau repas',
|
|
'body' => 'Un ami vient de publier son repas.',
|
|
'data' => ['meal_post_id' => 123],
|
|
],
|
|
[
|
|
'to' => 'ExponentPushToken[second]',
|
|
'title' => 'Nouveau repas',
|
|
'body' => 'Un ami vient de publier son repas.',
|
|
'data' => ['meal_post_id' => 123],
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('can be used from a notification via the expo channel alias', function () {
|
|
Http::fake([
|
|
'https://exp.host/*' => Http::response([
|
|
'data' => [
|
|
['status' => 'ok', 'id' => 'ticket-one'],
|
|
],
|
|
]),
|
|
]);
|
|
|
|
$user = User::factory()->create();
|
|
$user->deviceTokens()->create([
|
|
'expo_push_token' => 'ExponentPushToken[first]',
|
|
'platform' => 'ios',
|
|
]);
|
|
|
|
$user->notify(new class extends Notification
|
|
{
|
|
public function via(object $notifiable): array
|
|
{
|
|
return ['expo'];
|
|
}
|
|
|
|
public function toExpoPush(object $notifiable): array
|
|
{
|
|
return [
|
|
'title' => 'Nouveau repas',
|
|
'body' => 'Un ami vient de publier son repas.',
|
|
'data' => ['meal_post_id' => 123],
|
|
];
|
|
}
|
|
});
|
|
|
|
Http::assertSent(fn (Request $request) => $request->data()[0]['to'] === 'ExponentPushToken[first]');
|
|
});
|
|
|
|
it('removes device tokens rejected as not registered by expo', function () {
|
|
Http::fake([
|
|
'https://exp.host/*' => Http::response([
|
|
'data' => [
|
|
[
|
|
'status' => 'error',
|
|
'message' => '"ExponentPushToken[invalid]" is not a registered push notification recipient',
|
|
'details' => ['error' => 'DeviceNotRegistered'],
|
|
],
|
|
['status' => 'ok', 'id' => 'ticket-two'],
|
|
],
|
|
]),
|
|
]);
|
|
|
|
$user = User::factory()->create();
|
|
$invalidToken = $user->deviceTokens()->create([
|
|
'expo_push_token' => 'ExponentPushToken[invalid]',
|
|
'platform' => 'ios',
|
|
]);
|
|
$validToken = $user->deviceTokens()->create([
|
|
'expo_push_token' => 'ExponentPushToken[valid]',
|
|
'platform' => 'android',
|
|
]);
|
|
|
|
(new ExpoPushChannel)->send($user, expoPushTestNotification());
|
|
|
|
expect(DeviceToken::query()->whereKey($invalidToken->getKey())->exists())->toBeFalse()
|
|
->and(DeviceToken::query()->whereKey($validToken->getKey())->exists())->toBeTrue();
|
|
});
|
|
|
|
it('chunks expo push notifications into requests of one hundred messages', function () {
|
|
Http::fake([
|
|
'https://exp.host/*' => Http::response(['data' => []]),
|
|
]);
|
|
|
|
$user = User::factory()->create();
|
|
|
|
foreach (range(1, 101) as $number) {
|
|
$user->deviceTokens()->create([
|
|
'expo_push_token' => sprintf('ExponentPushToken[%03d]', $number),
|
|
'platform' => 'ios',
|
|
]);
|
|
}
|
|
|
|
(new ExpoPushChannel)->send($user, expoPushTestNotification());
|
|
|
|
Http::assertSentCount(2);
|
|
|
|
$requests = Http::recorded()
|
|
->map(fn (array $pair) => $pair[0]->data())
|
|
->values();
|
|
|
|
expect($requests[0])->toHaveCount(100)
|
|
->and($requests[1])->toHaveCount(1)
|
|
->and($requests[1][0]['to'])->toBe('ExponentPushToken[101]');
|
|
});
|
|
|
|
function expoPushTestNotification(): Notification
|
|
{
|
|
return new class extends Notification
|
|
{
|
|
public function toExpoPush(object $notifiable): array
|
|
{
|
|
return [
|
|
'title' => 'Nouveau repas',
|
|
'body' => 'Un ami vient de publier son repas.',
|
|
'data' => ['meal_post_id' => 123],
|
|
];
|
|
}
|
|
};
|
|
}
|