Files
cpo_test/laravel/tests/Feature/TaskApiTest.php
2026-02-06 23:26:56 +07:00

204 lines
5.5 KiB
PHP

<?php
namespace Tests\Feature;
use App\Enums\TaskStatus;
use App\Models\Task;
use App\Models\User;
use App\Notifications\TaskCreatedNotification;
use App\Notifications\TaskOverdueNotification;
use Laravel\Sanctum\Sanctum;
use Notification;
use Tests\TestCase;
use Throwable;
class TaskApiTest extends TestCase
{
public function test_guest_cannot_access_tasks_endpoints(): void
{
$this->getJson('/api/tasks')
->assertUnauthorized();
$this->postJson('/api/tasks')
->assertUnauthorized();
}
public function test_authenticated_user_can_create_task(): void
{
$user = User::factory()->create();
Sanctum::actingAs($user);
$payload = [
'title' => 'Новая задача',
'description' => 'Описание задачи',
'status' => TaskStatus::PENDING,
'due_date' => now()->addDay()->toDateString(),
];
$response = $this->postJson('/api/tasks', $payload);
$response
->assertCreated()
->assertJsonFragment([
'title' => 'Новая задача',
'status' => TaskStatus::PENDING,
]);
$this->assertDatabaseHas('tasks', [
'title' => 'Новая задача',
'user_id' => $user->id,
]);
}
/**
* @throws Throwable
*/
public function test_authenticated_user_can_create_task_and_notification_is_queued(): void
{
Notification::fake();
$user = User::factory()->create();
Sanctum::actingAs($user);
$payload = [
'title' => 'Новая задача',
'description' => 'Описание задачи',
'status' => TaskStatus::PENDING,
'due_date' => now()->addDay()->toDateString(),
];
$response = $this->postJson('/api/tasks', $payload);
$response
->assertCreated()
->assertHeader('Location')
->assertJsonFragment([
'title' => 'Новая задача',
'status' => TaskStatus::PENDING,
]);
$task = Task::where('title', 'Новая задача')->firstOrFail();
Notification::assertSentTo(
$user,
TaskCreatedNotification::class,
function (TaskCreatedNotification $notification) use ($task) {
return $notification->task->id === $task->id;
}
);
}
public function test_user_cannot_access_task_of_another_user(): void
{
$owner = User::factory()->create();
$wrong = User::factory()->create();
/**
* @var Task $task
*/
$task = Task::factory()->for($owner)->create();
Sanctum::actingAs($wrong);
$this->getJson("/api/tasks/$task->id")
->assertForbidden();
$this->putJson("/api/tasks/$task->id", [
'title' => 'йоу',
])->assertForbidden();
$this->deleteJson("/api/tasks/$task->id")
->assertForbidden();
}
/**
* @throws Throwable
*/
public function test_overdue_task_sends_notification(): void
{
Notification::fake();
$user = User::factory()->create();
/**
* @var Task $task
*/
$task = Task::factory()->for($user)->create([
'status' => TaskStatus::PENDING,
'due_date' => now()->subDay(),
'notified_at' => null,
]);
$this->artisan('tasks:notify-overdue')
->assertExitCode(0);
Notification::assertSentTo(
$user,
TaskOverdueNotification::class,
fn($notification) => $notification->task->id === $task->id
);
}
public function test_real_user_can_login_and_create_task(): void
{
$user = User::where('email', 'yo_yo@example.com')->first();
$loginResponse = $this->postJson('/api/login', [
'email' => 'yo_yo@example.com',
'password' => '123',
]);
$loginResponse->assertOk();
$token = $loginResponse->json('token');
$this->assertNotEmpty($token);
$payload = [
'title' => '123 задача',
'description' => 'Описание реальной задачи',
'status' => TaskStatus::PENDING,
'due_date' => now()->addDay()->toDateString(),
];
$taskResponse = $this->withHeader('Authorization', "Bearer $token")
->postJson('/api/tasks', $payload);
$taskResponse
->assertCreated()
->assertJsonFragment([
'title' => '123 задача',
'status' => TaskStatus::PENDING,
]);
$this->assertDatabaseHas('tasks', [
'title' => '123 задача',
'user_id' => $user->id,
]);
}
public function test_authenticated_user_can_list_tasks(): void
{
$user = User::factory()->create();
Task::factory(3)->for($user)->create();
Sanctum::actingAs($user);
$response = $this->getJson('/api/tasks');
$response->assertOk()
->assertJsonStructure([
'data' => [
'*' => [
'id',
'title',
'description',
'status',
'due_date',
'created_at',
'updated_at',
]
],
'links',
'meta',
]);
}
}