feat: followers and following
CI / 🧪 Tests Laravel (push) Successful in 2m27s
CI / 🐳 Build & Push Images (push) Successful in 43s

This commit is contained in:
2026-08-14 14:17:29 +02:00
parent 238a044d98
commit f752c28d99
2 changed files with 68 additions and 0 deletions
+4
View File
@@ -2,10 +2,12 @@
namespace App\Http\Resources;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Storage;
/** @mixin User */
class FollowResource extends JsonResource
{
/**
@@ -18,7 +20,9 @@ class FollowResource extends JsonResource
return [
'id' => $this->id,
'name' => $this->name,
'bio' => $this->bio,
'avatarUrl' => $this->avatar_url ? asset(Storage::url($this->avatar_url)) : null,
'accountVerified' => $this->account_verified_at !== null,
];
}
}
+64
View File
@@ -0,0 +1,64 @@
<?php
use App\Enums\FollowStatus;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
uses(RefreshDatabase::class);
it('lists only accepted followers with the profile fields required by the mobile app', function () {
$user = User::factory()->create();
$acceptedFollower = User::factory()->create([
'account_verified_at' => now(),
'bio' => 'Cuisine équilibrée.',
]);
$pendingFollower = User::factory()->create();
$acceptedFollower->following()->attach($user, ['status' => FollowStatus::Accepted]);
$pendingFollower->following()->attach($user, ['status' => FollowStatus::Pending]);
Sanctum::actingAs($user);
$this->getJson("/api/users/{$user->id}/followers?per_page=10")
->assertOk()
->assertJsonCount(1, 'data')
->assertJsonPath('data.0.id', $acceptedFollower->id)
->assertJsonPath('data.0.bio', 'Cuisine équilibrée.')
->assertJsonPath('data.0.accountVerified', true)
->assertJsonPath('meta.total', 1)
->assertJsonMissing(['id' => $pendingFollower->id]);
});
it('lists only accepted followed accounts and exposes the pagination total', function () {
$user = User::factory()->create();
$accepted = User::factory()->count(3)->create();
$pending = User::factory()->create();
$accepted->each(
fn (User $followed): mixed => $user->following()->attach(
$followed,
['status' => FollowStatus::Accepted],
),
);
$user->following()->attach($pending, ['status' => FollowStatus::Pending]);
Sanctum::actingAs($user);
$this->getJson("/api/users/{$user->id}/following?per_page=2")
->assertOk()
->assertJsonCount(2, 'data')
->assertJsonPath('meta.total', 3)
->assertJsonPath('meta.per_page', 2)
->assertJsonMissing(['id' => $pending->id]);
});
it('does not expose another users social lists', function () {
$user = User::factory()->create();
$otherUser = User::factory()->create();
Sanctum::actingAs($user);
$this->getJson("/api/users/{$otherUser->id}/followers")->assertForbidden();
$this->getJson("/api/users/{$otherUser->id}/following")->assertForbidden();
});