feat: followers and following
This commit is contained in:
@@ -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,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
Reference in New Issue
Block a user