Skip to content

Commit

Permalink
feat: implement filtering and sorting for post index endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
MrPunyapal committed Feb 28, 2025
1 parent 650e8a5 commit 838de6c
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 2 deletions.
5 changes: 3 additions & 2 deletions app/Http/Controllers/Api/PostController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use App\Http\Requests\StorePostRequest;
use App\Http\Requests\UpdatePostRequest;
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Response;

Expand All @@ -19,9 +20,9 @@ final class PostController extends Controller
/**
* Display a listing of the resource.
*/
public function index(): JsonResource
public function index(Request $request): JsonResource
{
return JsonResource::collection(Post::all());
return JsonResource::collection(Post::query()->filter($request->fluent())->paginate(10)->withQueryString());
}

/**
Expand Down
104 changes: 104 additions & 0 deletions tests/Feature/Http/Controllers/Api/PostControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,110 @@
->assertJson(['data' => $posts->toArray()]);
});

it('returns filtered posts based on search parameter', function () {
$user = User::factory()->create();
$postA = Post::factory()->create([
'title' => 'Test Post A',
'published_at' => now()->subDay(),
]);
$postB = Post::factory()->create([
'title' => 'Another Post B',
'published_at' => now()->addDay(),
]);

$response = $this->actingAs($user)
->getJson(action([PostController::class, 'index'], ['search' => 'Test']))
->assertSuccessful();

expect($response->json('data'))->toHaveCount(1);
expect($response->json('data.0.id'))->toBe($postA->id);
});

it('returns filtered posts based on published parameter', function () {
$user = User::factory()->create();
$postA = Post::factory()->create([
'title' => 'Test Post A',
'published_at' => now()->subDay(),
]);
$postB = Post::factory()->create([
'title' => 'Another Post B',
'published_at' => now()->addDay(),
]);

$response = $this->actingAs($user)
->getJson(action([PostController::class, 'index'], ['published' => true]))
->assertSuccessful();

expect($response->json('data'))->toHaveCount(1);
expect($response->json('data.0.id'))->toBe($postA->id);
});

it('can sort posts by specified column and direction', function () {
$user = User::factory()->create();
$postA = Post::factory()->create([
'title' => 'Test Post A',
'published_at' => now()->subDay(),
]);
$postB = Post::factory()->create([
'title' => 'Another Post B',
'published_at' => now()->addDay(),
]);

$response = $this->actingAs($user)
->getJson(action([PostController::class, 'index'], ['sortBy' => 'title', 'direction' => 'asc']))
->assertSuccessful();

expect($response->json('data'))->toHaveCount(2);
expect($response->json('data.0.id'))->toBe($postB->id);
expect($response->json('data.1.id'))->toBe($postA->id);
});

it('returns posts with default sorting when sort column is invalid', function () {
$user = User::factory()->create();
$postA = Post::factory()->create([
'title' => 'Test Post A',
'published_at' => now()->subDay(),
]);
$postB = Post::factory()->create([
'title' => 'Another Post B',
'published_at' => now()->addDay(),
]);

$response = $this->actingAs($user)
->getJson(action([PostController::class, 'index'], ['sortBy' => 'invalid_column']))
->assertSuccessful();

expect($response->json('data'))->toHaveCount(2);
});

it('combines multiple filter parameters', function () {
$user = User::factory()->create();
$postA = Post::factory()->create([
'title' => 'Test Post A',
'published_at' => now()->subDay(),
]);
$postB = Post::factory()->create([
'title' => 'Another Post B',
'published_at' => now()->addDay(),
]);
$postC = Post::factory()->create([
'title' => 'Test Post C',
'published_at' => now()->subDay(),
]);

$response = $this->actingAs($user)
->getJson(action([PostController::class, 'index'], [
'search' => 'Test',
'published' => true,
]))
->assertSuccessful();

expect($response->json('data'))->toHaveCount(2);
expect(collect($response->json('data'))->pluck('id')->toArray())
->toContain($postA->id, $postC->id)
->not->toContain($postB->id);
});

it('can create a new post', function () {
$data = Post::factory()->make()->toArray();

Expand Down

0 comments on commit 838de6c

Please sign in to comment.