travelTo(now()); $user = User::factory()->create(); $staleToken = $user->deviceTokens()->create([ 'expo_push_token' => 'ExponentPushToken[stale]', 'platform' => 'ios', ]); $recentToken = $user->deviceTokens()->create([ 'expo_push_token' => 'ExponentPushToken[recent]', 'platform' => 'android', ]); $staleToken->forceFill([ 'created_at' => now()->subDays(181), 'updated_at' => now()->subDays(181), ])->saveQuietly(); $recentToken->forceFill([ 'created_at' => now()->subDays(179), 'updated_at' => now()->subDays(179), ])->saveQuietly(); $this->artisan('device-tokens:prune-stale --days=180') ->expectsOutput('1 stale device token(s) pruned.') ->assertExitCode(0); expect(DeviceToken::query()->whereKey($staleToken->getKey())->exists())->toBeFalse() ->and(DeviceToken::query()->whereKey($recentToken->getKey())->exists())->toBeTrue(); }); it('rejects invalid retention days without deleting device tokens', function () { $user = User::factory()->create(); $deviceToken = $user->deviceTokens()->create([ 'expo_push_token' => 'ExponentPushToken[kept]', 'platform' => 'ios', ]); $deviceToken->forceFill([ 'created_at' => now()->subYear(), 'updated_at' => now()->subYear(), ])->saveQuietly(); $this->artisan('device-tokens:prune-stale --days=0') ->expectsOutput('The --days option must be an integer greater than zero.') ->assertExitCode(1); expect(DeviceToken::query()->whereKey($deviceToken->getKey())->exists())->toBeTrue(); });